mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 03:12:29 +00:00
ref(TS) Convert some components to TS (#13192)
This commit is contained in:
@@ -43,7 +43,7 @@ export class App extends AbstractApp {
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_createMainElement(component, props) {
|
||||
_createMainElement(component: React.ComponentType, props: any) {
|
||||
return (
|
||||
<JitsiThemeProvider>
|
||||
<AtlasKitThemeProvider mode = 'dark'>
|
||||
@@ -10,8 +10,9 @@ const route = {
|
||||
* Determines which route is to be rendered in order to depict a specific Redux
|
||||
* store.
|
||||
*
|
||||
* @param {any} _stateful - Used on web.
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export function _getRouteToRender() {
|
||||
export function _getRouteToRender(_stateful: any) {
|
||||
return Promise.resolve(route);
|
||||
}
|
||||
@@ -1,16 +1,21 @@
|
||||
|
||||
// @ts-expect-error
|
||||
import { generateRoomWithoutSeparator } from '@jitsi/js-utils/random';
|
||||
|
||||
import { IStateful } from '../base/app/types';
|
||||
import { isRoomValid } from '../base/conference/functions';
|
||||
import { isSupportedBrowser } from '../base/environment/environment';
|
||||
import { toState } from '../base/redux/functions';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import Conference from '../conference/components/web/Conference';
|
||||
import { getDeepLinkingPage } from '../deep-linking/functions';
|
||||
import UnsupportedDesktopBrowser from '../unsupported-browser/components/UnsupportedDesktopBrowser';
|
||||
import BlankPage from '../welcome/components/BlankPage';
|
||||
import WelcomePage from '../welcome/components/WelcomePage';
|
||||
import BlankPage from '../welcome/components/BlankPage.web';
|
||||
import WelcomePage from '../welcome/components/WelcomePage.web';
|
||||
import { getCustomLandingPageURL, isWelcomePageEnabled } from '../welcome/functions';
|
||||
|
||||
import { IReduxState } from './types';
|
||||
|
||||
/**
|
||||
* Determines which route is to be rendered in order to depict a specific Redux
|
||||
* store.
|
||||
@@ -19,7 +24,7 @@ import { getCustomLandingPageURL, isWelcomePageEnabled } from '../welcome/functi
|
||||
* {@code getState} function.
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export function _getRouteToRender(stateful) {
|
||||
export function _getRouteToRender(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
|
||||
return _getWebConferenceRoute(state) || _getWebWelcomePageRoute(state);
|
||||
@@ -32,7 +37,7 @@ export function _getRouteToRender(stateful) {
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {Promise|undefined}
|
||||
*/
|
||||
function _getWebConferenceRoute(state) {
|
||||
function _getWebConferenceRoute(state: IReduxState) {
|
||||
if (!isRoomValid(state['features/base/conference'].room)) {
|
||||
return;
|
||||
}
|
||||
@@ -45,8 +50,8 @@ function _getWebConferenceRoute(state) {
|
||||
// room into account.
|
||||
const { locationURL } = state['features/base/connection'];
|
||||
|
||||
if (window.location.href !== locationURL.href) {
|
||||
route.href = locationURL.href;
|
||||
if (window.location.href !== locationURL?.href) {
|
||||
route.href = locationURL?.href;
|
||||
|
||||
return Promise.resolve(route);
|
||||
}
|
||||
@@ -71,7 +76,7 @@ function _getWebConferenceRoute(state) {
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
function _getWebWelcomePageRoute(state) {
|
||||
function _getWebWelcomePageRoute(state: IReduxState) {
|
||||
const route = _getEmptyRoute();
|
||||
|
||||
if (isWelcomePageEnabled(state)) {
|
||||
@@ -102,7 +107,10 @@ function _getWebWelcomePageRoute(state) {
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
function _getEmptyRoute() {
|
||||
function _getEmptyRoute(): {
|
||||
component: React.ReactNode;
|
||||
href?: string;
|
||||
} {
|
||||
return {
|
||||
component: BlankPage,
|
||||
href: undefined
|
||||
@@ -1,4 +1,4 @@
|
||||
// @flow
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import { createConnectionEvent } from '../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../analytics/functions';
|
||||
@@ -10,6 +10,7 @@ import { inIframe } from '../base/util/iframeUtils';
|
||||
|
||||
import { reloadNow } from './actions';
|
||||
import { _getRouteToRender } from './getRouteToRender';
|
||||
import { IStore } from './types';
|
||||
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
@@ -39,7 +40,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
* @returns {Object} The new state that is the result of the reduction of the
|
||||
* specified {@code action}.
|
||||
*/
|
||||
function _connectionEstablished(store, next, action) {
|
||||
function _connectionEstablished(store: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
// In the Web app we explicitly do not want to display the hash and
|
||||
@@ -47,6 +48,7 @@ function _connectionEstablished(store, next, action) {
|
||||
// importantly, its params are used not only in jitsi-meet but also in
|
||||
// lib-jitsi-meet. Consequently, the time to remove the params is
|
||||
// determined by when no one needs them anymore.
|
||||
// @ts-ignore
|
||||
const { history, location } = window;
|
||||
|
||||
if (inIframe()) {
|
||||
@@ -57,12 +59,14 @@ function _connectionEstablished(store, next, action) {
|
||||
&& location
|
||||
&& history.length
|
||||
&& typeof history.replaceState === 'function') {
|
||||
// @ts-ignore
|
||||
const replacement = getURLWithoutParams(location);
|
||||
|
||||
// @ts-ignore
|
||||
if (location !== replacement) {
|
||||
history.replaceState(
|
||||
history.state,
|
||||
(document && document.title) || '',
|
||||
document?.title || '',
|
||||
replacement);
|
||||
}
|
||||
}
|
||||
@@ -81,7 +85,7 @@ function _connectionEstablished(store, next, action) {
|
||||
* @returns {Object}
|
||||
* @private
|
||||
*/
|
||||
function _connectionFailed({ dispatch, getState }, next, action) {
|
||||
function _connectionFailed({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
|
||||
// In the case of a split-brain error, reload early and prevent further
|
||||
// handling of the action.
|
||||
if (_isMaybeSplitBrainError(getState, action)) {
|
||||
@@ -104,7 +108,7 @@ function _connectionFailed({ dispatch, getState }, next, action) {
|
||||
* @private
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function _isMaybeSplitBrainError(getState, action) {
|
||||
function _isMaybeSplitBrainError(getState: IStore['getState'], action: AnyAction) {
|
||||
const { error } = action;
|
||||
const isShardChangedError = error
|
||||
&& error.message === 'item-not-found'
|
||||
@@ -116,7 +120,7 @@ function _isMaybeSplitBrainError(getState, action) {
|
||||
const { timeEstablished } = state['features/base/connection'];
|
||||
const { _immediateReloadThreshold } = state['features/base/config'];
|
||||
|
||||
const timeSinceConnectionEstablished = timeEstablished && Date.now() - timeEstablished;
|
||||
const timeSinceConnectionEstablished = Number(timeEstablished && Date.now() - timeEstablished);
|
||||
const reloadThreshold = typeof _immediateReloadThreshold === 'number' ? _immediateReloadThreshold : 1500;
|
||||
|
||||
const isWithinSplitBrainThreshold = !timeEstablished || timeSinceConnectionEstablished <= reloadThreshold;
|
||||
@@ -142,7 +146,7 @@ function _isMaybeSplitBrainError(getState, action) {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _navigate({ getState }) {
|
||||
function _navigate({ getState }: IStore) {
|
||||
const state = getState();
|
||||
const { app } = state['features/base/app'];
|
||||
|
||||
@@ -163,7 +167,7 @@ function _navigate({ getState }) {
|
||||
* @returns {Object} The new state that is the result of the reduction of the
|
||||
* specified {@code action}.
|
||||
*/
|
||||
function _setRoom(store, next, action) {
|
||||
function _setRoom(store: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
_navigate(store);
|
||||
@@ -186,7 +186,7 @@ export default class BaseApp<P> extends Component<P, IState> {
|
||||
* @abstract
|
||||
* @protected
|
||||
*/
|
||||
_createExtraElement() {
|
||||
_createExtraElement(): React.ReactElement | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -280,5 +280,7 @@ export default class BaseApp<P> extends Component<P, IState> {
|
||||
*
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderDialogContainer: () => React.ReactElement;
|
||||
_renderDialogContainer(): React.ReactElement | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,8 +112,8 @@ export interface IDeeplinkingMobileConfig extends IDeeplinkingPlatformConfig {
|
||||
export interface IDeeplinkingConfig {
|
||||
android?: IDeeplinkingMobileConfig;
|
||||
desktop?: IDeeplinkingPlatformConfig;
|
||||
disabled: boolean;
|
||||
hideLogo: boolean;
|
||||
disabled?: boolean;
|
||||
hideLogo?: boolean;
|
||||
ios?: IDeeplinkingMobileConfig;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ export interface INoiseSuppressionConfig {
|
||||
|
||||
export interface IConfig {
|
||||
_desktopSharingSourceDevice?: string;
|
||||
_screenshotHistoryRegionUrl?: string;
|
||||
_immediateReloadThreshold?: string;
|
||||
_screenshotHistoryRegionUrl?: number;
|
||||
analytics?: {
|
||||
amplitudeAPPKey?: string;
|
||||
blackListedEvents?: string[];
|
||||
|
||||
@@ -1,51 +1,48 @@
|
||||
// @flow
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getDisplayName } from '../../../../base/settings/functions.web';
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import Avatar from '../../../avatar/components/Avatar';
|
||||
import Video from '../../../media/components/web/Video';
|
||||
import { getLocalParticipant } from '../../../participants/functions';
|
||||
import { getDisplayName } from '../../../settings/functions.web';
|
||||
import { getLocalVideoTrack } from '../../../tracks/functions.web';
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
export type Props = {
|
||||
export interface IProps {
|
||||
|
||||
/**
|
||||
* Local participant id.
|
||||
*/
|
||||
_participantId: string,
|
||||
_participantId: string;
|
||||
|
||||
/**
|
||||
* Flag controlling whether the video should be flipped or not.
|
||||
*/
|
||||
flipVideo: boolean,
|
||||
flipVideo: boolean;
|
||||
|
||||
/**
|
||||
* The name of the user that is about to join.
|
||||
*/
|
||||
name: string,
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Flag signaling the visibility of camera preview.
|
||||
*/
|
||||
videoMuted: boolean,
|
||||
videoMuted: boolean;
|
||||
|
||||
/**
|
||||
* The JitsiLocalTrack to display.
|
||||
*/
|
||||
videoTrack: ?Object,
|
||||
};
|
||||
videoTrack?: Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component showing the video preview and device status.
|
||||
*
|
||||
* @param {Props} props - The props of the component.
|
||||
* @param {IProps} props - The props of the component.
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
function Preview(props: Props) {
|
||||
function Preview(props: IProps) {
|
||||
const { _participantId, flipVideo, name, videoMuted, videoTrack } = props;
|
||||
const className = flipVideo ? 'flipVideoX' : '';
|
||||
|
||||
@@ -83,19 +80,19 @@ function Preview(props: Props) {
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @param {Props} ownProps - The own props of the component.
|
||||
* @returns {Props}
|
||||
* @param {IProps} ownProps - The own props of the component.
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
function _mapStateToProps(state: IReduxState, ownProps: any) {
|
||||
const name = getDisplayName(state);
|
||||
const { id: _participantId } = getLocalParticipant(state);
|
||||
const { id: _participantId } = getLocalParticipant(state) ?? {};
|
||||
|
||||
return {
|
||||
_participantId,
|
||||
flipVideo: state['features/base/settings'].localFlipX,
|
||||
_participantId: _participantId ?? '',
|
||||
flipVideo: Boolean(state['features/base/settings'].localFlipX),
|
||||
name,
|
||||
videoMuted: ownProps.videoTrack ? ownProps.videoMuted : state['features/base/media'].video.muted,
|
||||
videoTrack: ownProps.videoTrack || (getLocalVideoTrack(state['features/base/tracks']) || {}).jitsiTrack
|
||||
videoTrack: ownProps.videoTrack || getLocalVideoTrack(state['features/base/tracks'])?.jitsiTrack
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,38 +1,29 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../i18n/functions';
|
||||
import Button from '../../../ui/components/web/Button';
|
||||
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link InlineDialogFailure}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Allows to retry the call that previously didn't succeed.
|
||||
*/
|
||||
onRetry: Function,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
onRetry: Function;
|
||||
|
||||
/**
|
||||
* Indicates whether the support link should be shown in case of an error.
|
||||
*/
|
||||
showSupportLink: Boolean,
|
||||
};
|
||||
showSupportLink: Boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inline dialog that represents a failure and allows a retry.
|
||||
*/
|
||||
class InlineDialogFailure extends Component<Props> {
|
||||
class InlineDialogFailure extends Component<IProps> {
|
||||
/**
|
||||
* Renders the content of this component.
|
||||
*
|
||||
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { getLocalizedDateFormatter, getLocalizedDurationFormatter } from '../../../i18n/dateUtil';
|
||||
import { translate } from '../../../i18n/functions';
|
||||
@@ -10,43 +9,47 @@ import { IconTrash } from '../../../icons/svg';
|
||||
import Container from './Container';
|
||||
import Text from './Text';
|
||||
|
||||
type Props = {
|
||||
interface IMeeting {
|
||||
date: Date;
|
||||
duration?: number;
|
||||
elementAfter?: React.ReactElement;
|
||||
time: Date[];
|
||||
title: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Indicates if the list is disabled or not.
|
||||
*/
|
||||
disabled: boolean,
|
||||
disabled: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if the URL should be hidden or not.
|
||||
*/
|
||||
hideURL: boolean,
|
||||
|
||||
/**
|
||||
* Function to be invoked when an item is pressed. The item's URL is passed.
|
||||
*/
|
||||
onPress: Function,
|
||||
hideURL?: boolean;
|
||||
|
||||
/**
|
||||
* Rendered when the list is empty. Should be a rendered element.
|
||||
*/
|
||||
listEmptyComponent: Object,
|
||||
listEmptyComponent: React.ReactNode;
|
||||
|
||||
/**
|
||||
* An array of meetings.
|
||||
*/
|
||||
meetings: Array<Object>,
|
||||
meetings: IMeeting[];
|
||||
|
||||
/**
|
||||
* Handler for deleting an item.
|
||||
*/
|
||||
onItemDelete?: Function,
|
||||
onItemDelete?: Function;
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
* Function to be invoked when an item is pressed. The item's URL is passed.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
onPress: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a date string for a given date.
|
||||
@@ -55,7 +58,7 @@ type Props = {
|
||||
* @private
|
||||
* @returns {string}
|
||||
*/
|
||||
function _toDateString(date) {
|
||||
function _toDateString(date: Date) {
|
||||
return getLocalizedDateFormatter(date).format('ll');
|
||||
}
|
||||
|
||||
@@ -67,7 +70,7 @@ function _toDateString(date) {
|
||||
* @private
|
||||
* @returns {string}
|
||||
*/
|
||||
function _toTimeString(times) {
|
||||
function _toTimeString(times: Date[]) {
|
||||
if (times && times.length > 0) {
|
||||
return (
|
||||
times
|
||||
@@ -84,13 +87,13 @@ function _toTimeString(times) {
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class MeetingsList extends Component<Props> {
|
||||
class MeetingsList extends Component<IProps> {
|
||||
/**
|
||||
* Constructor of the MeetingsList component.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._onPress = this._onPress.bind(this);
|
||||
@@ -123,8 +126,6 @@ class MeetingsList extends Component<Props> {
|
||||
return null;
|
||||
}
|
||||
|
||||
_onPress: string => Function;
|
||||
|
||||
/**
|
||||
* Returns a function that is used in the onPress callback of the items.
|
||||
*
|
||||
@@ -132,18 +133,16 @@ class MeetingsList extends Component<Props> {
|
||||
* @private
|
||||
* @returns {Function}
|
||||
*/
|
||||
_onPress(url) {
|
||||
_onPress(url: string) {
|
||||
const { disabled, onPress } = this.props;
|
||||
|
||||
if (!disabled && url && typeof onPress === 'function') {
|
||||
return () => onPress(url);
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
_onKeyPress: string => Function;
|
||||
|
||||
/**
|
||||
* Returns a function that is used in the onPress callback of the items.
|
||||
*
|
||||
@@ -151,22 +150,20 @@ class MeetingsList extends Component<Props> {
|
||||
* @private
|
||||
* @returns {Function}
|
||||
*/
|
||||
_onKeyPress(url) {
|
||||
_onKeyPress(url: string) {
|
||||
const { disabled, onPress } = this.props;
|
||||
|
||||
if (!disabled && url && typeof onPress === 'function') {
|
||||
return e => {
|
||||
return (e: React.KeyboardEvent) => {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
onPress(url);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
_onDelete: Object => Function;
|
||||
|
||||
/**
|
||||
* Returns a function that is used on the onDelete callback.
|
||||
*
|
||||
@@ -174,18 +171,16 @@ class MeetingsList extends Component<Props> {
|
||||
* @private
|
||||
* @returns {Function}
|
||||
*/
|
||||
_onDelete(item) {
|
||||
_onDelete(item: Object) {
|
||||
const { onItemDelete } = this.props;
|
||||
|
||||
return evt => {
|
||||
return (evt: React.MouseEvent) => {
|
||||
evt.stopPropagation();
|
||||
|
||||
onItemDelete && onItemDelete(item);
|
||||
onItemDelete?.(item);
|
||||
};
|
||||
}
|
||||
|
||||
_onDeleteKeyPress: Object => Function;
|
||||
|
||||
/**
|
||||
* Returns a function that is used on the onDelete keypress callback.
|
||||
*
|
||||
@@ -193,10 +188,10 @@ class MeetingsList extends Component<Props> {
|
||||
* @private
|
||||
* @returns {Function}
|
||||
*/
|
||||
_onDeleteKeyPress(item) {
|
||||
_onDeleteKeyPress(item: Object) {
|
||||
const { onItemDelete } = this.props;
|
||||
|
||||
return e => {
|
||||
return (e: React.KeyboardEvent) => {
|
||||
if (onItemDelete && (e.key === ' ' || e.key === 'Enter')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -205,8 +200,6 @@ class MeetingsList extends Component<Props> {
|
||||
};
|
||||
}
|
||||
|
||||
_renderItem: (Object, number) => React$Node;
|
||||
|
||||
/**
|
||||
* Renders an item for the list.
|
||||
*
|
||||
@@ -214,7 +207,7 @@ class MeetingsList extends Component<Props> {
|
||||
* @param {number} index - The index of the item.
|
||||
* @returns {Node}
|
||||
*/
|
||||
_renderItem(meeting, index) {
|
||||
_renderItem(meeting: IMeeting, index: number) {
|
||||
const {
|
||||
date,
|
||||
duration,
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { Item } from '../../types';
|
||||
@@ -11,18 +9,18 @@ import Text from './Text';
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link NavigateSectionListItem}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Function to be invoked when an item is pressed. The item's URL is passed.
|
||||
*/
|
||||
onPress: ?Function,
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* A item containing data to be rendered.
|
||||
*/
|
||||
item: Item
|
||||
};
|
||||
item: Item;
|
||||
|
||||
/**
|
||||
* Function to be invoked when an item is pressed. The item's URL is passed.
|
||||
*/
|
||||
onPress?: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a React/Web {@link Component} for displaying an item in a
|
||||
@@ -30,7 +28,7 @@ type Props = {
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
export default class NavigateSectionListItem<P: Props>
|
||||
export default class NavigateSectionListItem<P extends IProps>
|
||||
extends Component<P> {
|
||||
|
||||
/**
|
||||
@@ -1,17 +1,15 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { Section } from '../../types';
|
||||
|
||||
import Text from './Text';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* A section containing the data to be rendered.
|
||||
*/
|
||||
section: Section
|
||||
section: Section;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20,7 +18,7 @@ type Props = {
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
export default class NavigateSectionListSectionHeader extends Component<Props> {
|
||||
export default class NavigateSectionListSectionHeader extends Component<IProps> {
|
||||
/**
|
||||
* Renders the content of this component.
|
||||
*
|
||||
@@ -1,44 +1,42 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { Section } from '../../types';
|
||||
|
||||
import Container from './Container';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Rendered when the list is empty. Should be a rendered element.
|
||||
*/
|
||||
ListEmptyComponent: Object,
|
||||
ListEmptyComponent: Object;
|
||||
|
||||
/**
|
||||
* Used to extract a unique key for a given item at the specified index.
|
||||
* Key is used for caching and as the react key to track item re-ordering.
|
||||
*/
|
||||
keyExtractor: Function,
|
||||
|
||||
/**
|
||||
* Returns a React component that renders each Item in the list.
|
||||
*/
|
||||
renderItem: Function,
|
||||
|
||||
/**
|
||||
* Returns a React component that renders the header for every section.
|
||||
*/
|
||||
renderSectionHeader: Function,
|
||||
|
||||
/**
|
||||
* An array of sections.
|
||||
*/
|
||||
sections: Array<Section>,
|
||||
keyExtractor: Function;
|
||||
|
||||
/**
|
||||
* Defines what happens when an item in the section list is clicked.
|
||||
*/
|
||||
onItemClick: Function
|
||||
};
|
||||
onItemClick: Function;
|
||||
|
||||
/**
|
||||
* Returns a React component that renders each Item in the list.
|
||||
*/
|
||||
renderItem: Function;
|
||||
|
||||
/**
|
||||
* Returns a React component that renders the header for every section.
|
||||
*/
|
||||
renderSectionHeader: Function;
|
||||
|
||||
/**
|
||||
* An array of sections.
|
||||
*/
|
||||
sections: Array<Section>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a React/Web {@link Component} for displaying a list with
|
||||
@@ -47,7 +45,7 @@ type Props = {
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
export default class SectionList extends Component<Props> {
|
||||
export default class SectionList extends Component<IProps> {
|
||||
/**
|
||||
* Renders the content of this component.
|
||||
*
|
||||
@@ -1,14 +1,11 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import { isVpaasMeeting } from '../../../../jaas/functions';
|
||||
import { translate } from '../../../i18n/functions';
|
||||
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The CSS style of the element with CSS class {@code rightwatermark}.
|
||||
*
|
||||
@@ -21,38 +18,33 @@ const _RIGHT_WATERMARK_STYLE = {
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Watermarks}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The link used to navigate to on logo click.
|
||||
*/
|
||||
_logoLink: string,
|
||||
_logoLink: string;
|
||||
|
||||
/**
|
||||
* The url for the logo.
|
||||
*/
|
||||
_logoUrl: string,
|
||||
_logoUrl?: string;
|
||||
|
||||
/**
|
||||
* If the Jitsi watermark should be displayed or not.
|
||||
*/
|
||||
_showJitsiWatermark: boolean,
|
||||
_showJitsiWatermark: boolean;
|
||||
|
||||
/**
|
||||
* The default value for the Jitsi logo URL.
|
||||
*/
|
||||
defaultJitsiLogoURL?: string;
|
||||
|
||||
/**
|
||||
* Whether the watermark should have a `top` and `left` value.
|
||||
*/
|
||||
noMargins: boolean;
|
||||
|
||||
/**
|
||||
* The default value for the Jitsi logo URL.
|
||||
*/
|
||||
defaultJitsiLogoURL: ?string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link Watermarks}.
|
||||
@@ -62,31 +54,31 @@ type State = {
|
||||
/**
|
||||
* The url to open when clicking the brand watermark.
|
||||
*/
|
||||
brandWatermarkLink: string,
|
||||
brandWatermarkLink: string;
|
||||
|
||||
/**
|
||||
* Whether or not the brand watermark should be displayed.
|
||||
*/
|
||||
showBrandWatermark: boolean,
|
||||
showBrandWatermark: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the show the "powered by Jitsi.org" link.
|
||||
*/
|
||||
showPoweredBy: boolean
|
||||
showPoweredBy: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Web Component which renders watermarks such as Jits, brand, powered by,
|
||||
* etc.
|
||||
*/
|
||||
class Watermarks extends Component<Props, State> {
|
||||
class Watermarks extends Component<IProps, State> {
|
||||
/**
|
||||
* Initializes a new Watermarks 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);
|
||||
|
||||
const showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
|
||||
@@ -179,7 +171,7 @@ class Watermarks extends Component<Props, State> {
|
||||
};
|
||||
|
||||
reactElement = (<div
|
||||
className = { className }
|
||||
className = { className } // @ts-ignore
|
||||
style = { style } />);
|
||||
|
||||
if (_logoLink) {
|
||||
@@ -227,9 +219,9 @@ class Watermarks extends Component<Props, State> {
|
||||
*
|
||||
* @param {Object} state - Snapshot of Redux store.
|
||||
* @param {Object} ownProps - Component's own props.
|
||||
* @returns {Props}
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
function _mapStateToProps(state: IReduxState, ownProps: any) {
|
||||
const {
|
||||
customizationReady,
|
||||
customizationFailed,
|
||||
@@ -248,7 +240,7 @@ function _mapStateToProps(state, ownProps) {
|
||||
customizationReady && !customizationFailed
|
||||
&& SHOW_JITSI_WATERMARK)
|
||||
|| !isValidRoom;
|
||||
let _logoUrl = logoImageUrl;
|
||||
let _logoUrl: string | undefined = logoImageUrl;
|
||||
let _logoLink = logoClickUrl;
|
||||
|
||||
if (useDynamicBrandingData) {
|
||||
@@ -272,4 +264,4 @@ function _mapStateToProps(state, ownProps) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(_mapStateToProps)(translate(Watermarks));
|
||||
export default translate(connect(_mapStateToProps)(Watermarks));
|
||||
@@ -2,7 +2,6 @@ import React, { Component, ComponentType } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import { IReactionEmojiProps } from '../../../../reactions/constants';
|
||||
import JitsiPortal from '../../../../toolbox/components/web/JitsiPortal';
|
||||
import { showOverflowDrawer } from '../../../../toolbox/functions.web';
|
||||
|
||||
@@ -25,11 +24,6 @@ interface IProps {
|
||||
*/
|
||||
_overflowDrawer: boolean;
|
||||
|
||||
/**
|
||||
* Array of reactions to be displayed.
|
||||
*/
|
||||
_reactionsQueue: Array<IReactionEmojiProps>;
|
||||
|
||||
/**
|
||||
* True if the UI is in a compact state where we don't show dialogs.
|
||||
*/
|
||||
|
||||
@@ -1,55 +1,49 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { createCalendarClickedEvent } from '../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../analytics/functions';
|
||||
import { IStore } from '../../app/types';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
import { IconPlus } from '../../base/icons/svg';
|
||||
import Tooltip from '../../base/tooltip/components/Tooltip';
|
||||
import { updateCalendarEvent } from '../actions';
|
||||
import { updateCalendarEvent } from '../actions.web';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AddMeetingUrlButton}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The calendar ID associated with the calendar event.
|
||||
*/
|
||||
calendarId: string,
|
||||
calendarId: string;
|
||||
|
||||
/**
|
||||
* Invoked to add a meeting URL to a calendar event.
|
||||
*/
|
||||
dispatch: Dispatch<any>,
|
||||
dispatch: IStore['dispatch'];
|
||||
|
||||
/**
|
||||
* The ID of the calendar event that will have a meeting URL added on click.
|
||||
*/
|
||||
eventId: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
eventId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A React Component for adding a meeting URL to an existing calendar event.
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class AddMeetingUrlButton extends Component<Props> {
|
||||
class AddMeetingUrlButton extends Component<IProps> {
|
||||
/**
|
||||
* Initializes a new {@code AddMeetingUrlButton} instance.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
// Bind event handler so it is only bound once for every instance.
|
||||
@@ -76,8 +70,6 @@ class AddMeetingUrlButton extends Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_onClick: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action to adding a meeting URL to a calendar event.
|
||||
*
|
||||
@@ -91,8 +83,6 @@ class AddMeetingUrlButton extends Component<Props> {
|
||||
dispatch(updateCalendarEvent(eventId, calendarId));
|
||||
}
|
||||
|
||||
_onKeyPress: (Object) => void;
|
||||
|
||||
/**
|
||||
* KeyPress handler for accessibility.
|
||||
*
|
||||
@@ -100,7 +90,7 @@ class AddMeetingUrlButton extends Component<Props> {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onKeyPress(e) {
|
||||
_onKeyPress(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
this._onClick();
|
||||
@@ -1,71 +1,64 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { createCalendarClickedEvent } from '../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../analytics/functions';
|
||||
import { IReduxState } from '../../app/types';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
import { IconCalendar } from '../../base/icons/svg';
|
||||
import AbstractPage from '../../base/react/components/AbstractPage';
|
||||
import Spinner from '../../base/ui/components/web/Spinner';
|
||||
import { openSettingsDialog } from '../../settings/actions';
|
||||
import { openSettingsDialog } from '../../settings/actions.web';
|
||||
import { SETTINGS_TABS } from '../../settings/constants';
|
||||
import { refreshCalendar } from '../actions';
|
||||
import { refreshCalendar } from '../actions.web';
|
||||
import { ERRORS } from '../constants';
|
||||
|
||||
import CalendarListContent from './CalendarListContent';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
import CalendarListContent from './CalendarListContent.web';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link CalendarList}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The error object containing details about any error that has occurred
|
||||
* while interacting with calendar integration.
|
||||
*/
|
||||
_calendarError: ?Object,
|
||||
_calendarError?: { error: string; };
|
||||
|
||||
/**
|
||||
* Whether or not a calendar may be connected for fetching calendar events.
|
||||
*/
|
||||
_hasIntegrationSelected: boolean,
|
||||
_hasIntegrationSelected: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not events have been fetched from a calendar.
|
||||
*/
|
||||
_hasLoadedEvents: boolean,
|
||||
_hasLoadedEvents: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if the list is disabled or not.
|
||||
*/
|
||||
disabled: boolean,
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* The Redux dispatch function.
|
||||
*/
|
||||
dispatch: Function,
|
||||
|
||||
/**
|
||||
* The translate function.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
dispatch: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component to display a list of events from the user's calendar.
|
||||
*/
|
||||
class CalendarList extends AbstractPage<Props> {
|
||||
class CalendarList extends AbstractPage<IProps> {
|
||||
/**
|
||||
* Initializes a new {@code CalendarList} instance.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
@@ -87,7 +80,7 @@ class CalendarList extends AbstractPage<Props> {
|
||||
return (
|
||||
CalendarListContent
|
||||
? <CalendarListContent
|
||||
disabled = { disabled }
|
||||
disabled = { Boolean(disabled) }
|
||||
listEmptyComponent
|
||||
= { this._getRenderListEmptyComponent() } />
|
||||
: null
|
||||
@@ -102,7 +95,7 @@ class CalendarList extends AbstractPage<Props> {
|
||||
* @returns {React$Component}
|
||||
*/
|
||||
_getErrorMessage() {
|
||||
const { _calendarError = {}, t } = this.props;
|
||||
const { _calendarError = { error: undefined }, t } = this.props;
|
||||
|
||||
let errorMessageKey = 'calendarSync.error.generic';
|
||||
let showRefreshButton = true;
|
||||
@@ -142,8 +135,6 @@ class CalendarList extends AbstractPage<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_getRenderListEmptyComponent: () => Object;
|
||||
|
||||
/**
|
||||
* Returns a list empty component if a custom one has to be rendered instead
|
||||
* of the default one in the {@link NavigateSectionList}.
|
||||
@@ -210,8 +201,6 @@ class CalendarList extends AbstractPage<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_onOpenSettings: () => void;
|
||||
|
||||
/**
|
||||
* Opens {@code SettingsDialog}.
|
||||
*
|
||||
@@ -224,8 +213,6 @@ class CalendarList extends AbstractPage<Props> {
|
||||
this.props.dispatch(openSettingsDialog(SETTINGS_TABS.CALENDAR));
|
||||
}
|
||||
|
||||
_onKeyPressOpenSettings: (Object) => void;
|
||||
|
||||
/**
|
||||
* KeyPress handler for accessibility.
|
||||
*
|
||||
@@ -233,15 +220,13 @@ class CalendarList extends AbstractPage<Props> {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onKeyPressOpenSettings(e) {
|
||||
_onKeyPressOpenSettings(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
this._onOpenSettings();
|
||||
}
|
||||
}
|
||||
|
||||
_onRefreshEvents: () => void;
|
||||
|
||||
|
||||
/**
|
||||
* Gets an updated list of calendar events.
|
||||
@@ -266,7 +251,7 @@ class CalendarList extends AbstractPage<Props> {
|
||||
* _hasLoadedEvents: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const {
|
||||
error,
|
||||
events,
|
||||
@@ -1,47 +1,46 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { createCalendarClickedEvent, createCalendarSelectedEvent } from '../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../analytics/functions';
|
||||
import { appNavigate } from '../../app/actions';
|
||||
import { appNavigate } from '../../app/actions.web';
|
||||
import { IReduxState } from '../../app/types';
|
||||
import MeetingsList from '../../base/react/components/web/MeetingsList';
|
||||
|
||||
import AddMeetingUrlButton from './AddMeetingUrlButton';
|
||||
import JoinButton from './JoinButton';
|
||||
import AddMeetingUrlButton from './AddMeetingUrlButton.web';
|
||||
import JoinButton from './JoinButton.web';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link CalendarListContent}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The calendar event list.
|
||||
*/
|
||||
_eventList: Array<Object>,
|
||||
_eventList: Array<Object>;
|
||||
|
||||
/**
|
||||
* Indicates if the list is disabled or not.
|
||||
*/
|
||||
disabled: boolean,
|
||||
disabled: boolean;
|
||||
|
||||
/**
|
||||
* The Redux dispatch function.
|
||||
*/
|
||||
dispatch: Function,
|
||||
dispatch: Function;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
listEmptyComponent: React$Node,
|
||||
};
|
||||
listEmptyComponent: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component to display a list of events from a connected calendar.
|
||||
*/
|
||||
class CalendarListContent extends Component<Props> {
|
||||
class CalendarListContent extends Component<IProps> {
|
||||
/**
|
||||
* Default values for the component's props.
|
||||
*/
|
||||
@@ -54,7 +53,7 @@ class CalendarListContent extends Component<Props> {
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
@@ -93,8 +92,6 @@ class CalendarListContent extends Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_onJoinPress: (Object, string) => Function;
|
||||
|
||||
/**
|
||||
* Handles the list's navigate action.
|
||||
*
|
||||
@@ -103,14 +100,12 @@ class CalendarListContent extends Component<Props> {
|
||||
* @param {string} url - The url string to navigate to.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onJoinPress(event, url) {
|
||||
_onJoinPress(event: React.KeyboardEvent, url: string) {
|
||||
event.stopPropagation();
|
||||
|
||||
this._onPress(url, 'meeting.join');
|
||||
}
|
||||
|
||||
_onPress: (string, ?string) => Function;
|
||||
|
||||
/**
|
||||
* Handles the list's navigate action.
|
||||
*
|
||||
@@ -120,14 +115,12 @@ class CalendarListContent extends Component<Props> {
|
||||
* associated with this action.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onPress(url, analyticsEventName = 'meeting.tile') {
|
||||
_onPress(url: string, analyticsEventName = 'meeting.tile') {
|
||||
sendAnalytics(createCalendarClickedEvent(analyticsEventName));
|
||||
|
||||
this.props.dispatch(appNavigate(url));
|
||||
}
|
||||
|
||||
_toDisplayableItem: Object => Object;
|
||||
|
||||
/**
|
||||
* Creates a displayable object from an event.
|
||||
*
|
||||
@@ -135,7 +128,7 @@ class CalendarListContent extends Component<Props> {
|
||||
* @private
|
||||
* @returns {Object}
|
||||
*/
|
||||
_toDisplayableItem(event) {
|
||||
_toDisplayableItem(event: any) {
|
||||
return {
|
||||
elementAfter: event.url
|
||||
? <JoinButton
|
||||
@@ -161,7 +154,7 @@ class CalendarListContent extends Component<Props> {
|
||||
* _eventList: Array<Object>
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state: Object) {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
return {
|
||||
_eventList: state['features/calendar-sync'].events
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
@@ -10,30 +9,25 @@ import Tooltip from '../../base/tooltip/components/Tooltip';
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link JoinButton}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The function called when the button is pressed.
|
||||
*/
|
||||
onPress: Function,
|
||||
onPress: Function;
|
||||
|
||||
/**
|
||||
* The meeting URL associated with the {@link JoinButton} instance.
|
||||
*/
|
||||
url: string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A React Component for joining an existing calendar meeting.
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class JoinButton extends Component<Props> {
|
||||
class JoinButton extends Component<IProps> {
|
||||
|
||||
/**
|
||||
* Initializes a new {@code JoinButton} instance.
|
||||
@@ -41,7 +35,7 @@ class JoinButton extends Component<Props> {
|
||||
* @param {*} props - The read-only properties with which the new instance
|
||||
* is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
// Bind event handler so it is only bound once for every instance.
|
||||
@@ -73,8 +67,6 @@ class JoinButton extends Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_onClick: (Object) => void;
|
||||
|
||||
/**
|
||||
* Callback invoked when the component is clicked.
|
||||
*
|
||||
@@ -82,12 +74,10 @@ class JoinButton extends Component<Props> {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onClick(event) {
|
||||
_onClick(event?: React.MouseEvent) {
|
||||
this.props.onPress(event, this.props.url);
|
||||
}
|
||||
|
||||
_onKeyPress: (Object) => void;
|
||||
|
||||
/**
|
||||
* KeyPress handler for accessibility.
|
||||
*
|
||||
@@ -95,7 +85,7 @@ class JoinButton extends Component<Props> {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onKeyPress(e) {
|
||||
_onKeyPress(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
this._onClick();
|
||||
@@ -28,7 +28,7 @@ const DEFAULT_STATE = {
|
||||
|
||||
export interface ICalendarSyncState {
|
||||
authorization?: string;
|
||||
error?: Object;
|
||||
error?: { error: string; };
|
||||
events: Array<{
|
||||
calendarId: string;
|
||||
endDate: string;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
// @flow
|
||||
|
||||
// @ts-expect-error
|
||||
import { jitsiLocalStorage } from '@jitsi/js-utils';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { createChromeExtensionBannerEvent } from '../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../analytics/functions';
|
||||
import { IReduxState } from '../../app/types';
|
||||
import { getCurrentConference } from '../../base/conference/functions';
|
||||
import checkChromeExtensionsInstalled from '../../base/environment/checkChromeExtensionsInstalled';
|
||||
import { IJitsiConference } from '../../base/conference/reducer';
|
||||
import checkChromeExtensionsInstalled from '../../base/environment/checkChromeExtensionsInstalled.web';
|
||||
import {
|
||||
isMobileBrowser
|
||||
} from '../../base/environment/utils';
|
||||
@@ -18,9 +20,6 @@ import { browser } from '../../base/lib-jitsi-meet';
|
||||
import { isVpaasMeeting } from '../../jaas/functions';
|
||||
import logger from '../logger';
|
||||
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
/**
|
||||
@@ -33,54 +32,53 @@ const DONT_SHOW_AGAIN_CHECKED = 'hide_chrome_extension_banner';
|
||||
/**
|
||||
* The type of the React {@code PureComponent} props of {@link ChromeExtensionBanner}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Contains info about installed/to be installed chrome extension(s).
|
||||
*/
|
||||
bannerCfg: Object,
|
||||
bannerCfg: {
|
||||
chromeExtensionsInfo?: string[];
|
||||
edgeUrl?: string;
|
||||
url?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Conference data, if any.
|
||||
*/
|
||||
conference: Object,
|
||||
conference?: IJitsiConference;
|
||||
|
||||
/**
|
||||
* Whether I am the current recorder.
|
||||
*/
|
||||
iAmRecorder: boolean,
|
||||
iAmRecorder: boolean;
|
||||
|
||||
/**
|
||||
* Whether it's a vpaas meeting or not.
|
||||
*/
|
||||
isVpaas: boolean,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
};
|
||||
isVpaas: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the React {@link PureComponent} state of {@link ChromeExtensionBanner}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Keeps the current value of dont show again checkbox.
|
||||
*/
|
||||
dontShowAgainChecked: boolean,
|
||||
interface IState {
|
||||
|
||||
/**
|
||||
* Tells whether user pressed install extension or close button.
|
||||
*/
|
||||
closePressed: boolean,
|
||||
closePressed: boolean;
|
||||
|
||||
/**
|
||||
* Keeps the current value of dont show again checkbox.
|
||||
*/
|
||||
dontShowAgainChecked: boolean;
|
||||
|
||||
/**
|
||||
* Tells whether should show the banner or not based on extension being installed or not.
|
||||
*/
|
||||
shouldShow: boolean,
|
||||
};
|
||||
shouldShow: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a React {@link PureComponent} which displays a banner having a link to the chrome extension.
|
||||
@@ -88,14 +86,16 @@ type State = {
|
||||
* @class ChromeExtensionBanner
|
||||
* @augments PureComponent
|
||||
*/
|
||||
class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
class ChromeExtensionBanner extends PureComponent<IProps, IState> {
|
||||
isEdge: boolean;
|
||||
|
||||
/**
|
||||
* Initializes a new {@code ChromeExtensionBanner} instance.
|
||||
*
|
||||
* @param {Object} props - The read-only React {@code PureComponent} props with
|
||||
* which the new instance is to be initialized.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dontShowAgainChecked: false,
|
||||
@@ -118,7 +118,7 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
async componentDidUpdate(prevProps) {
|
||||
async componentDidUpdate(prevProps: IProps) {
|
||||
if (!this._isSupportedEnvironment()) {
|
||||
return;
|
||||
}
|
||||
@@ -137,8 +137,7 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
const hasExtensions = await checkChromeExtensionsInstalled(this.props.bannerCfg);
|
||||
|
||||
if (
|
||||
hasExtensions
|
||||
&& hasExtensions.length
|
||||
hasExtensions?.length
|
||||
&& hasExtensions.every(ext => !ext)
|
||||
&& !this.state.shouldShow
|
||||
) {
|
||||
@@ -160,8 +159,6 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
&& !this.props.isVpaas;
|
||||
}
|
||||
|
||||
_onClosePressed: () => void;
|
||||
|
||||
/**
|
||||
* Closes the banner for the current session.
|
||||
*
|
||||
@@ -172,8 +169,6 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
this.setState({ closePressed: true });
|
||||
}
|
||||
|
||||
_onCloseKeyPress: (Object) => void;
|
||||
|
||||
/**
|
||||
* KeyPress handler for accessibility.
|
||||
*
|
||||
@@ -181,15 +176,13 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onCloseKeyPress(e) {
|
||||
_onCloseKeyPress(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
this._onClosePressed();
|
||||
}
|
||||
}
|
||||
|
||||
_onInstallExtensionClick: () => void;
|
||||
|
||||
/**
|
||||
* Opens the chrome extension page.
|
||||
*
|
||||
@@ -203,8 +196,6 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
this.setState({ closePressed: true });
|
||||
}
|
||||
|
||||
_onInstallExtensionKeyPress: (Object) => void;
|
||||
|
||||
/**
|
||||
* KeyPress handler for accessibility.
|
||||
*
|
||||
@@ -212,15 +203,13 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onInstallExtensionKeyPress(e) {
|
||||
_onInstallExtensionKeyPress(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
this._onClosePressed();
|
||||
}
|
||||
}
|
||||
|
||||
_shouldNotRender: () => boolean;
|
||||
|
||||
/**
|
||||
* Checks whether the banner should not be rendered.
|
||||
*
|
||||
@@ -240,15 +229,13 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
|| this.props.iAmRecorder;
|
||||
}
|
||||
|
||||
_onDontShowAgainChange: (object: Object) => void;
|
||||
|
||||
/**
|
||||
* Handles the current `don't show again` checkbox state.
|
||||
*
|
||||
* @param {Object} event - Input change event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDontShowAgainChange(event) {
|
||||
_onDontShowAgainChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
this.setState({ dontShowAgainChecked: event.target.checked });
|
||||
}
|
||||
|
||||
@@ -258,7 +245,7 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
render(): React.ReactNode {
|
||||
if (this._shouldNotRender()) {
|
||||
if (this.state.dontShowAgainChecked) {
|
||||
jitsiLocalStorage.setItem(DONT_SHOW_AGAIN_CHECKED, 'true');
|
||||
@@ -340,12 +327,12 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
|
||||
* @param {Object} state - Redux state.
|
||||
* @returns {Object}
|
||||
*/
|
||||
const _mapStateToProps = state => {
|
||||
const _mapStateToProps = (state: IReduxState) => {
|
||||
return {
|
||||
// Using emptyObject so that we don't change the reference every time when _mapStateToProps is called.
|
||||
bannerCfg: state['features/base/config'].chromeExtensionBanner || emptyObject,
|
||||
conference: getCurrentConference(state),
|
||||
iAmRecorder: state['features/base/config'].iAmRecorder,
|
||||
iAmRecorder: Boolean(state['features/base/config'].iAmRecorder),
|
||||
isVpaas: isVpaasMeeting(state)
|
||||
};
|
||||
};
|
||||
@@ -60,6 +60,8 @@ export function getDeepLinkingPage(state: IReduxState) {
|
||||
const { room } = state['features/base/conference'];
|
||||
const { launchInWeb } = state['features/deep-linking'];
|
||||
const deeplinking = state['features/base/config'].deeplinking || {};
|
||||
|
||||
// @ts-ignore
|
||||
const { appScheme } = deeplinking?.[Platform.OS as keyof typeof deeplinking] || {};
|
||||
|
||||
// Show only if we are about to join a conference.
|
||||
|
||||
@@ -1,56 +1,47 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { IReduxState, IStore } from '../../app/types';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import MeetingsList from '../../base/react/components/web/MeetingsList';
|
||||
import { deleteRecentListEntry } from '../actions';
|
||||
import { isRecentListEnabled, toDisplayableList } from '../functions';
|
||||
import { isRecentListEnabled, toDisplayableList } from '../functions.web';
|
||||
|
||||
import AbstractRecentList from './AbstractRecentList';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link RecentList}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Renders the list disabled.
|
||||
*/
|
||||
disabled: boolean,
|
||||
|
||||
/**
|
||||
* The redux store's {@code dispatch} function.
|
||||
*/
|
||||
dispatch: Dispatch<any>,
|
||||
|
||||
/**
|
||||
* The translate function.
|
||||
*/
|
||||
t: Function,
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The recent list from the Redux store.
|
||||
*/
|
||||
_recentList: Array<Object>
|
||||
};
|
||||
_recentList: Array<any>;
|
||||
|
||||
/**
|
||||
* Renders the list disabled.
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* The redux store's {@code dispatch} function.
|
||||
*/
|
||||
dispatch: IStore['dispatch'];
|
||||
}
|
||||
|
||||
/**
|
||||
* The cross platform container rendering the list of the recently joined rooms.
|
||||
*
|
||||
*/
|
||||
class RecentList extends AbstractRecentList<Props> {
|
||||
_getRenderListEmptyComponent: () => React$Node;
|
||||
_onPress: string => {};
|
||||
|
||||
class RecentList extends AbstractRecentList<IProps> {
|
||||
/**
|
||||
* Initializes a new {@code RecentList} instance.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._getRenderListEmptyComponent
|
||||
@@ -59,15 +50,13 @@ class RecentList extends AbstractRecentList<Props> {
|
||||
this._onItemDelete = this._onItemDelete.bind(this);
|
||||
}
|
||||
|
||||
_onItemDelete: Object => void;
|
||||
|
||||
/**
|
||||
* Deletes a recent entry.
|
||||
*
|
||||
* @param {Object} entry - The entry to be deleted.
|
||||
* @inheritdoc
|
||||
*/
|
||||
_onItemDelete(entry) {
|
||||
_onItemDelete(entry: Object) {
|
||||
this.props.dispatch(deleteRecentListEntry(entry));
|
||||
}
|
||||
|
||||
@@ -88,7 +77,7 @@ class RecentList extends AbstractRecentList<Props> {
|
||||
|
||||
return (
|
||||
<MeetingsList
|
||||
disabled = { disabled }
|
||||
disabled = { Boolean(disabled) }
|
||||
hideURL = { true }
|
||||
listEmptyComponent = { this._getRenderListEmptyComponent() }
|
||||
meetings = { recentList }
|
||||
@@ -107,7 +96,7 @@ class RecentList extends AbstractRecentList<Props> {
|
||||
* _recentList: Array
|
||||
* }}
|
||||
*/
|
||||
export function _mapStateToProps(state: Object) {
|
||||
export function _mapStateToProps(state: IReduxState) {
|
||||
return {
|
||||
_recentList: state['features/recent-list']
|
||||
};
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
/**
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-expect-error
|
||||
import { generateRoomWithoutSeparator } from '@jitsi/js-utils/random';
|
||||
import { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { createWelcomePageEvent } from '../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../analytics/functions';
|
||||
@@ -14,7 +15,7 @@ import { isRecentListEnabled } from '../../recent-list/functions';
|
||||
/**
|
||||
* {@code AbstractWelcomePage}'s React {@code Component} prop types.
|
||||
*/
|
||||
export interface IProps {
|
||||
export interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Whether the calendar functionality is enabled or not.
|
||||
@@ -57,12 +58,23 @@ export interface IProps {
|
||||
dispatch: IStore['dispatch'];
|
||||
}
|
||||
|
||||
interface IState {
|
||||
animateTimeoutId?: number;
|
||||
generateRoomNames?: string;
|
||||
generatedRoomName: string;
|
||||
insecureRoomName: boolean;
|
||||
joining: boolean;
|
||||
room: string;
|
||||
roomPlaceholder: string;
|
||||
updateTimeoutId?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base (abstract) class for container component rendering the welcome page.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
export class AbstractWelcomePage<P extends IProps> extends Component<P> {
|
||||
export class AbstractWelcomePage<P extends IProps> extends Component<P, IState> {
|
||||
_mounted: boolean | undefined;
|
||||
|
||||
/**
|
||||
@@ -81,6 +93,7 @@ export class AbstractWelcomePage<P extends IProps> extends Component<P> {
|
||||
state = {
|
||||
animateTimeoutId: undefined,
|
||||
generatedRoomName: '',
|
||||
generateRoomNames: undefined,
|
||||
insecureRoomName: false,
|
||||
joining: false,
|
||||
room: '',
|
||||
@@ -142,7 +155,7 @@ export class AbstractWelcomePage<P extends IProps> extends Component<P> {
|
||||
|
||||
if (word.length > 1) {
|
||||
animateTimeoutId
|
||||
= setTimeout(
|
||||
= window.setTimeout(
|
||||
() => {
|
||||
this._animateRoomNameChanging(
|
||||
word.substring(1, word.length));
|
||||
@@ -171,7 +184,9 @@ export class AbstractWelcomePage<P extends IProps> extends Component<P> {
|
||||
*
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_doRenderInsecureRoomNameWarning: () => React.Component<any>;
|
||||
_doRenderInsecureRoomNameWarning(): JSX.Element | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles joining. Either by clicking on 'Join' button
|
||||
@@ -213,7 +228,7 @@ export class AbstractWelcomePage<P extends IProps> extends Component<P> {
|
||||
_onRoomChange(value: string) {
|
||||
this.setState({
|
||||
room: value,
|
||||
insecureRoomName: this.props._enableInsecureRoomNameWarning && value && isInsecureRoomName(value)
|
||||
insecureRoomName: Boolean(this.props._enableInsecureRoomNameWarning && value && isInsecureRoomName(value))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -240,7 +255,7 @@ export class AbstractWelcomePage<P extends IProps> extends Component<P> {
|
||||
_updateRoomName() {
|
||||
const generatedRoomName = generateRoomWithoutSeparator();
|
||||
const roomPlaceholder = '';
|
||||
const updateTimeoutId = setTimeout(this._updateRoomName, 10000);
|
||||
const updateTimeoutId = window.setTimeout(this._updateRoomName, 10000);
|
||||
|
||||
this._clearTimeouts();
|
||||
this.setState(
|
||||
@@ -268,7 +283,7 @@ export function _mapStateToProps(state: IReduxState) {
|
||||
_enableInsecureRoomNameWarning: state['features/base/config'].enableInsecureRoomNameWarning || false,
|
||||
_moderatedRoomServiceUrl: state['features/base/config'].moderatedRoomServiceUrl,
|
||||
_recentListEnabled: isRecentListEnabled(),
|
||||
_room: state['features/base/conference'].room,
|
||||
_room: state['features/base/conference'].room ?? '',
|
||||
_settings: state['features/base/settings']
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,37 +1,40 @@
|
||||
// @flow
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Tabs}.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Accessibility label for the tabs container.
|
||||
*
|
||||
*/
|
||||
accessibilityLabel: string,
|
||||
accessibilityLabel: string;
|
||||
|
||||
/**
|
||||
* Tabs information.
|
||||
*/
|
||||
tabs: Object
|
||||
};
|
||||
tabs: {
|
||||
content: any;
|
||||
id: string;
|
||||
label: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A React component that implements tabs.
|
||||
*
|
||||
* @returns {ReactElement} The component.
|
||||
*/
|
||||
const Tabs = ({ accessibilityLabel, tabs }: Props) => {
|
||||
const Tabs = ({ accessibilityLabel, tabs }: IProps) => {
|
||||
const [ current, setCurrent ] = useState(0);
|
||||
|
||||
const onClick = useCallback(index => event => {
|
||||
const onClick = useCallback(index => (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
setCurrent(index);
|
||||
}, []);
|
||||
|
||||
const onKeyDown = useCallback(index => event => {
|
||||
const onKeyDown = useCallback(index => (event: React.KeyboardEvent) => {
|
||||
let newIndex = null;
|
||||
|
||||
if (event.key === 'ArrowLeft') {
|
||||
@@ -52,6 +55,7 @@ const Tabs = ({ accessibilityLabel, tabs }: Props) => {
|
||||
useEffect(() => {
|
||||
// this test is needed to make sure the effect is triggered because of user actually changing tab
|
||||
if (document.activeElement?.getAttribute('role') === 'tab') {
|
||||
// @ts-ignore
|
||||
document.querySelector(`#${`${tabs[current].id}-tab`}`)?.focus();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* global interfaceConfig */
|
||||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@@ -13,7 +11,7 @@ import RecentList from '../../recent-list/components/RecentList.web';
|
||||
import SettingsButton from '../../settings/components/web/SettingsButton';
|
||||
import { SETTINGS_TABS } from '../../settings/constants';
|
||||
|
||||
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
|
||||
import { AbstractWelcomePage, IProps, _mapStateToProps } from './AbstractWelcomePage';
|
||||
import Tabs from './Tabs';
|
||||
|
||||
/**
|
||||
@@ -28,7 +26,15 @@ export const ROOM_NAME_VALIDATE_PATTERN_STR = '^[^?&:\u0022\u0027%#]+$';
|
||||
*
|
||||
* @augments AbstractWelcomePage
|
||||
*/
|
||||
class WelcomePage extends AbstractWelcomePage {
|
||||
class WelcomePage extends AbstractWelcomePage<IProps> {
|
||||
_additionalContentRef: HTMLDivElement | null;
|
||||
_additionalToolbarContentRef: HTMLDivElement | null;
|
||||
_additionalCardRef: HTMLDivElement | null;
|
||||
_roomInputRef: HTMLInputElement | null;
|
||||
_additionalCardTemplate: HTMLTemplateElement | null;
|
||||
_additionalContentTemplate: HTMLTemplateElement | null;
|
||||
_additionalToolbarContentTemplate: HTMLTemplateElement | null;
|
||||
|
||||
/**
|
||||
* Default values for {@code WelcomePage} component's properties.
|
||||
*
|
||||
@@ -44,7 +50,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@@ -83,7 +89,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* @type {HTMLTemplateElement|null}
|
||||
*/
|
||||
this._additionalCardTemplate = document.getElementById(
|
||||
'welcome-page-additional-card-template');
|
||||
'welcome-page-additional-card-template') as HTMLTemplateElement;
|
||||
|
||||
/**
|
||||
* The template to use as the main content for the welcome page. If
|
||||
@@ -93,7 +99,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* @type {HTMLTemplateElement|null}
|
||||
*/
|
||||
this._additionalContentTemplate = document.getElementById(
|
||||
'welcome-page-additional-content-template');
|
||||
'welcome-page-additional-content-template') as HTMLTemplateElement;
|
||||
|
||||
/**
|
||||
* The template to use as the additional content for the welcome page header toolbar.
|
||||
@@ -104,7 +110,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
*/
|
||||
this._additionalToolbarContentTemplate = document.getElementById(
|
||||
'settings-toolbar-additional-content-template'
|
||||
);
|
||||
) as HTMLTemplateElement;
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
this._onFormSubmit = this._onFormSubmit.bind(this);
|
||||
@@ -136,19 +142,19 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
}
|
||||
|
||||
if (this._shouldShowAdditionalContent()) {
|
||||
this._additionalContentRef.appendChild(
|
||||
this._additionalContentTemplate.content.cloneNode(true));
|
||||
this._additionalContentRef?.appendChild(
|
||||
this._additionalContentTemplate?.content.cloneNode(true) as Node);
|
||||
}
|
||||
|
||||
if (this._shouldShowAdditionalToolbarContent()) {
|
||||
this._additionalToolbarContentRef.appendChild(
|
||||
this._additionalToolbarContentTemplate.content.cloneNode(true)
|
||||
this._additionalToolbarContentRef?.appendChild(
|
||||
this._additionalToolbarContentTemplate?.content.cloneNode(true) as Node
|
||||
);
|
||||
}
|
||||
|
||||
if (this._shouldShowAdditionalCard()) {
|
||||
this._additionalCardRef.appendChild(
|
||||
this._additionalCardTemplate.content.cloneNode(true)
|
||||
this._additionalCardRef?.appendChild(
|
||||
this._additionalCardTemplate?.content.cloneNode(true) as Node
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -236,7 +242,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
className = 'welcome-page-button'
|
||||
id = 'enter_room_button'
|
||||
onClick = { this._onFormSubmit }
|
||||
tabIndex = '0'
|
||||
tabIndex = { 0 }
|
||||
type = 'button'>
|
||||
{ t('welcomepage.startMeeting') }
|
||||
</button>
|
||||
@@ -301,7 +307,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onFormSubmit(event) {
|
||||
_onFormSubmit(event: React.FormEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!this._roomInputRef || this._roomInputRef.reportValidity()) {
|
||||
@@ -319,7 +325,9 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* the EventTarget.
|
||||
* @protected
|
||||
*/
|
||||
_onRoomChange(event) {
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
_onRoomChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
super._onRoomChange(event.target.value);
|
||||
}
|
||||
|
||||
@@ -332,8 +340,9 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
const {
|
||||
t,
|
||||
_deeplinkingCfg: {
|
||||
ios = {},
|
||||
android = {}
|
||||
ios = { downloadLink: undefined },
|
||||
android = { fDroidUrl: undefined,
|
||||
downloadLink: undefined }
|
||||
}
|
||||
} = this.props;
|
||||
|
||||
@@ -424,7 +433,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setAdditionalCardRef(el) {
|
||||
_setAdditionalCardRef(el: HTMLDivElement) {
|
||||
this._additionalCardRef = el;
|
||||
}
|
||||
|
||||
@@ -437,7 +446,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setAdditionalContentRef(el) {
|
||||
_setAdditionalContentRef(el: HTMLDivElement) {
|
||||
this._additionalContentRef = el;
|
||||
}
|
||||
|
||||
@@ -450,7 +459,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setAdditionalToolbarContentRef(el) {
|
||||
_setAdditionalToolbarContentRef(el: HTMLDivElement) {
|
||||
this._additionalToolbarContentRef = el;
|
||||
}
|
||||
|
||||
@@ -462,7 +471,7 @@ class WelcomePage extends AbstractWelcomePage {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setRoomInputRef(el) {
|
||||
_setRoomInputRef(el: HTMLInputElement) {
|
||||
this._roomInputRef = el;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user