ref: Convert some reducers to TS (#12065)

This commit is contained in:
Robert Pintilii 2022-08-26 12:54:16 +03:00 committed by GitHub
parent 3bd3be4df0
commit 1010955393
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 183 additions and 81 deletions

View File

@ -40,7 +40,20 @@ import { IInviteState } from '../invite/reducer';
import { IJaaSState } from '../jaas/reducer';
import { ILargeVideoState } from '../large-video/reducer';
import { ILobbyState } from '../lobby/reducer';
import { IMobileAudioModeState } from '../mobile/audio-mode/reducer';
import { IBackgroundState } from '../mobile/background/reducer';
import { IMobileExternalApiState } from '../mobile/external-api/reducer';
import { IFullScreenState } from '../mobile/full-screen/reducer';
import { IMobileWatchOSState } from '../mobile/watchos/reducer';
import { INoAudioSignalState } from '../no-audio-signal/reducer';
import { INoiseDetectionState } from '../noise-detection/reducer';
import { INoiseSuppressionState } from '../noise-suppression/reducer';
import { INotificationsState } from '../notifications/reducer';
import { IOverlayState } from '../overlay/reducer';
import { IPollsState } from '../polls/reducer';
import { IPowerMonitorState } from '../power-monitor/reducer';
import { IPrejoinState } from '../prejoin/reducer';
import { IReactionsState } from '../reactions/reducer';
export interface IStore {
dispatch: Function,
@ -51,6 +64,7 @@ export interface IState {
'features/analytics': IAnalyticsState,
'features/authentication': IAuthenticationState,
'features/av-moderation': IAVModerationState,
'features/background': IBackgroundState,
'features/base/app': IAppState,
'features/base/audio-only': IAudioOnlyState,
'features/base/conference': IConferenceState,
@ -85,12 +99,25 @@ export interface IState {
'features/feedback': IFeedbackState,
'features/filmstrip': IFilmstripState,
'features/follow-me': IFollowMeState,
'features/full-screen': IFullScreenState,
'features/gifs': IGifsState,
'features/google-api': IGoogleApiState,
'features/invite': IInviteState,
'features/jaas': IJaaSState,
'features/large-video': ILargeVideoState,
'features/lobby': ILobbyState,
'features/mobile/audio-mode': IMobileAudioModeState,
'features/mobile/external-api': IMobileExternalApiState,
'features/mobile/watchos': IMobileWatchOSState,
'features/no-audio-signal': INoAudioSignalState,
'features/noise-detection': INoiseDetectionState,
'features/noise-suppression': INoiseSuppressionState,
'features/notifications': INotificationsState,
'features/overlay': IOverlayState,
'features/participants-pane': IParticipantsState,
'features/polls': IPollsState,
'features/power-monitor': IPowerMonitorState,
'features/prejoin': IPrejoinState,
'features/reactions': IReactionsState,
'features/testing': ITestingState
}

View File

@ -16,7 +16,7 @@ import { IState, IStore } from '../../app/types';
* from the specified target by setting the specified properties to the
* specified values.
*/
export function assign<T extends Object>(target: T, source: T): T {
export function assign<T extends Object>(target: T, source: Partial<T>): T {
let t = target;
for (const property in source) { // eslint-disable-line guard-for-in

View File

@ -1,15 +1,19 @@
// @flow
import { equals, set, ReducerRegistry } from '../../base/redux';
import ReducerRegistry from '../../base/redux/ReducerRegistry';
import { equals, set } from '../../base/redux/functions';
import { _SET_AUDIOMODE_DEVICES, _SET_AUDIOMODE_SUBSCRIPTIONS } from './actionTypes';
export interface IMobileAudioModeState {
devices: Object[];
subscriptions: Object[];
}
const DEFAULT_STATE = {
devices: [],
subscriptions: []
};
ReducerRegistry.register('features/mobile/audio-mode', (state = DEFAULT_STATE, action) => {
ReducerRegistry.register('features/mobile/audio-mode', (state: IMobileAudioModeState = DEFAULT_STATE, action) => {
switch (action.type) {
case _SET_AUDIOMODE_DEVICES: {
const { devices } = action;

View File

@ -1,12 +1,15 @@
// @flow
import { ReducerRegistry } from '../../base/redux';
import ReducerRegistry from '../../base/redux/ReducerRegistry';
import {
_SET_APP_STATE_LISTENER,
APP_STATE_CHANGED
} from './actionTypes';
export interface IBackgroundState {
appState: string;
appStateListener?: Function;
}
/**
* The default/initial redux state of the feature background.
*/
@ -14,7 +17,7 @@ const DEFAULT_STATE = {
appState: 'active'
};
ReducerRegistry.register('features/background', (state = DEFAULT_STATE, action) => {
ReducerRegistry.register('features/background', (state: IBackgroundState = DEFAULT_STATE, action) => {
switch (action.type) {
case _SET_APP_STATE_LISTENER:
return {

View File

@ -1,14 +1,16 @@
// @flow
import { ReducerRegistry } from '../../base/redux';
import ReducerRegistry from '../../base/redux/ReducerRegistry';
import { SCREEN_SHARE_PARTICIPANTS_UPDATED } from './actionTypes';
export interface IMobileExternalApiState {
screenShares: string[];
}
const DEFAULT_STATE = {
screenShares: []
};
ReducerRegistry.register('features/mobile/external-api', (state = DEFAULT_STATE, action) => {
ReducerRegistry.register('features/mobile/external-api', (state: IMobileExternalApiState = DEFAULT_STATE, action) => {
switch (action.type) {
case SCREEN_SHARE_PARTICIPANTS_UPDATED: {
return {

View File

@ -1,10 +1,12 @@
// @flow
import { ReducerRegistry } from '../../base/redux';
import ReducerRegistry from '../../base/redux/ReducerRegistry';
import { _SET_IMMERSIVE_LISTENER } from './actionTypes';
ReducerRegistry.register('features/full-screen', (state = {}, action) => {
export interface IFullScreenState {
listener?: Function;
}
ReducerRegistry.register('features/full-screen', (state: IFullScreenState = {}, action) => {
switch (action.type) {
case _SET_IMMERSIVE_LISTENER:
return {

View File

@ -1,9 +1,14 @@
// @flow
import { assign, ReducerRegistry } from '../../base/redux';
import ReducerRegistry from '../../base/redux/ReducerRegistry';
import { assign } from '../../base/redux/functions';
import { SET_CONFERENCE_TIMESTAMP, SET_SESSION_ID, SET_WATCH_REACHABLE } from './actionTypes';
export interface IMobileWatchOSState {
conferenceTimestamp?: number;
sessionID: number;
watchReachable?: boolean;
}
const INITIAL_STATE = {
sessionID: new Date().getTime()
};
@ -11,7 +16,7 @@ const INITIAL_STATE = {
/**
* Reduces the Redux actions of the feature features/mobile/watchos.
*/
ReducerRegistry.register('features/mobile/watchos', (state = INITIAL_STATE, action) => {
ReducerRegistry.register('features/mobile/watchos', (state: IMobileWatchOSState = INITIAL_STATE, action) => {
switch (action.type) {
case SET_CONFERENCE_TIMESTAMP: {
return assign(state, {

View File

@ -1,13 +1,16 @@
// @flow
import { ReducerRegistry, set } from '../base/redux';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import { set } from '../base/redux/functions';
import { SET_NO_AUDIO_SIGNAL_NOTIFICATION_UID } from './actionTypes';
export interface INoAudioSignalState {
noAudioSignalNotificationUid?: number;
}
/**
* Reduces the redux actions of the feature no audio signal.
*/
ReducerRegistry.register('features/no-audio-signal', (state = {}, action) => {
ReducerRegistry.register('features/no-audio-signal', (state: INoAudioSignalState = {}, action) => {
switch (action.type) {
case SET_NO_AUDIO_SIGNAL_NOTIFICATION_UID:
return set(state, 'noAudioSignalNotificationUid', action.uid);

View File

@ -1,13 +1,16 @@
// @flow
import { ReducerRegistry, set } from '../base/redux';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import { set } from '../base/redux/functions';
import { SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID } from './actionTypes';
export interface INoiseDetectionState {
noisyAudioInputNotificationUid?: number;
}
/**
* Reduces the redux actions of noise detection feature.
*/
ReducerRegistry.register('features/noise-detection', (state = {}, action) => {
ReducerRegistry.register('features/noise-detection', (state: INoiseDetectionState = {}, action) => {
switch (action.type) {
case SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID:
return set(state, 'noisyAudioInputNotificationUid', action.uid);

View File

@ -1,5 +1,3 @@
// @flow
/**
* The standard time when auto-disappearing notifications should disappear.
*/

View File

@ -1,6 +1,4 @@
// @flow
import { ReducerRegistry } from '../base/redux';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import {
CLEAR_NOTIFICATIONS,
@ -20,6 +18,22 @@ const DEFAULT_STATE = {
notifications: []
};
interface INotification {
component: Object;
props: {
appearance?: string;
descriptionKey?: string;
titleKey: string;
};
timeout: number;
uid: string;
}
export interface INotificationsState {
enabled: boolean;
notifications: INotification[];
}
/**
* Reduces redux actions which affect the display of notifications.
*
@ -29,7 +43,7 @@ const DEFAULT_STATE = {
* specified {@code action}.
*/
ReducerRegistry.register('features/notifications',
(state = DEFAULT_STATE, action) => {
(state: INotificationsState = DEFAULT_STATE, action) => {
switch (action.type) {
case CLEAR_NOTIFICATIONS:
return {
@ -75,9 +89,9 @@ ReducerRegistry.register('features/notifications',
* @returns {Object[]} A new array with an updated order of the notification
* queue.
*/
function _insertNotificationByPriority(notifications, notification) {
function _insertNotificationByPriority(notifications: INotification[], notification: INotification) {
const newNotificationPriority
= NOTIFICATION_TYPE_PRIORITIES[notification.props.appearance] || 0;
= NOTIFICATION_TYPE_PRIORITIES[notification.props.appearance ?? ''] || 0;
// Default to putting the new notification at the end of the queue.
let insertAtLocation = notifications.length;
@ -88,7 +102,7 @@ function _insertNotificationByPriority(notifications, notification) {
for (let i = 1; i < notifications.length; i++) {
const queuedNotification = notifications[i];
const queuedNotificationPriority
= NOTIFICATION_TYPE_PRIORITIES[queuedNotification.props.appearance]
= NOTIFICATION_TYPE_PRIORITIES[queuedNotification.props.appearance ?? '']
|| 0;
if (queuedNotificationPriority < newNotificationPriority) {

View File

@ -1,7 +1,6 @@
// @flow
import { CONFIG_WILL_LOAD, LOAD_CONFIG_ERROR, SET_CONFIG } from '../base/config';
import { assign, ReducerRegistry, set } from '../base/redux';
import { CONFIG_WILL_LOAD, LOAD_CONFIG_ERROR, SET_CONFIG } from '../base/config/actionTypes';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import { assign, set } from '../base/redux/functions';
import {
MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED,
@ -9,19 +8,27 @@ import {
TOGGLE_SLOW_GUM_OVERLAY
} from './actionTypes';
export interface IOverlayState {
browser?: string;
fatalError?: Error;
isMediaPermissionPromptVisible?: boolean;
isSlowGUMOverlayVisible?: boolean;
loadConfigOverlayVisible?: boolean;
}
/**
* Reduces the redux actions of the feature overlay.
*
* FIXME: these pieces of state should probably be in a different place.
*/
ReducerRegistry.register('features/overlay', (state = { }, action) => {
ReducerRegistry.register('features/overlay', (state: IOverlayState = { }, action) => {
switch (action.type) {
case CONFIG_WILL_LOAD:
return _setShowLoadConfigOverlay(state, Boolean(action.room));
case LOAD_CONFIG_ERROR:
case SET_CONFIG:
return _setShowLoadConfigOverlay(false);
return _setShowLoadConfigOverlay(state, false);
case MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED:
return _mediaPermissionPromptVisibilityChanged(state, action);
@ -47,8 +54,8 @@ ReducerRegistry.register('features/overlay', (state = { }, action) => {
* the specified action.
*/
function _mediaPermissionPromptVisibilityChanged(
state,
{ browser, isVisible }) {
state: IOverlayState,
{ browser, isVisible }: {browser?: string, isVisible?: boolean}) {
return assign(state, {
browser,
isMediaPermissionPromptVisible: isVisible
@ -66,8 +73,8 @@ function _mediaPermissionPromptVisibilityChanged(
* the specified action.
*/
function _toggleSlowGUMOverlay(
state,
{ isVisible }) {
state: IOverlayState,
{ isVisible }: {isVisible?: boolean}) {
return assign(state, {
isSlowGUMOverlayVisible: isVisible
});
@ -81,7 +88,7 @@ function _toggleSlowGUMOverlay(
* @returns {Object} The new state of the feature overlay after the reduction of
* the specified action.
*/
function _setShowLoadConfigOverlay(state, show) {
function _setShowLoadConfigOverlay(state: IOverlayState, show?: boolean) {
return set(state, 'loadConfigOverlayVisible', show);
}
@ -95,6 +102,6 @@ function _setShowLoadConfigOverlay(state, show) {
* @returns {Object}
* @private
*/
function _setFatalError(state, { fatalError }) {
function _setFatalError(state: IOverlayState, { fatalError }: {fatalError?: Error}) {
return set(state, 'fatalError', fatalError);
}

View File

@ -1,14 +1,12 @@
// @flow
import React from 'react';
import Icon from '../base/icons/components/Icon';
import {
Icon,
IconCameraEmpty,
IconCameraEmptyDisabled,
IconMicrophoneEmpty,
IconMicrophoneEmptySlash
} from '../base/icons';
} from '../base/icons/svg';
/**
* Reducer key for the feature.
@ -44,8 +42,8 @@ export type QuickActionButtonType = 'Mute' | 'AskToUnmute' | 'None';
* Enum of possible participant mute button states.
*/
export const QUICK_ACTION_BUTTON: {
MUTE: QuickActionButtonType,
ASK_TO_UNMUTE: QuickActionButtonType,
MUTE: QuickActionButtonType,
NONE: QuickActionButtonType
} = {
MUTE: 'Mute',
@ -56,7 +54,7 @@ export const QUICK_ACTION_BUTTON: {
/**
* Icon mapping for possible participant audio states.
*/
export const AudioStateIcons: {[MediaState]: React$Element<any> | null} = {
export const AudioStateIcons = {
[MEDIA_STATE.DOMINANT_SPEAKER]: (
<Icon
className = 'jitsi-icon-dominant-speaker'

View File

@ -1,4 +1,4 @@
import { ReducerRegistry } from '../base/redux';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import {
PARTICIPANTS_PANE_CLOSE,
@ -7,6 +7,13 @@ import {
} from './actionTypes';
import { REDUCER_KEY } from './constants';
export interface IParticipantsPane {
isOpen: boolean;
participantsVolume: {
[participantId: string]: number;
}
}
const DEFAULT_STATE = {
isOpen: false,
participantsVolume: {}
@ -16,7 +23,7 @@ const DEFAULT_STATE = {
* Listen for actions that mutate the participants pane state.
*/
ReducerRegistry.register(
REDUCER_KEY, (state = DEFAULT_STATE, action) => {
REDUCER_KEY, (state: IParticipantsPane = DEFAULT_STATE, action) => {
switch (action.type) {
case PARTICIPANTS_PANE_CLOSE:
return {

View File

@ -1,6 +1,4 @@
// @flow
import { ReducerRegistry } from '../base/redux';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import {
CHANGE_VOTE,
@ -11,7 +9,7 @@ import {
RETRACT_VOTE,
RESET_NB_UNREAD_POLLS
} from './actionTypes';
import type { Answer } from './types';
import { Answer, Poll } from './types';
const INITIAL_STATE = {
polls: {},
@ -20,7 +18,14 @@ const INITIAL_STATE = {
nbUnreadPolls: 0
};
ReducerRegistry.register('features/polls', (state = INITIAL_STATE, action) => {
export interface IPollsState {
nbUnreadPolls: number;
polls: {
[pollId: string]: Poll
};
}
ReducerRegistry.register('features/polls', (state: IPollsState = INITIAL_STATE, action) => {
switch (action.type) {
case CHANGE_VOTE: {
@ -66,7 +71,7 @@ ReducerRegistry.register('features/polls', (state = INITIAL_STATE, action) => {
// The answer is added to an existing poll
case RECEIVE_ANSWER: {
const { pollId, answer }: { pollId: string; answer: Answer } = action;
const { pollId, answer }: { answer: Answer, pollId: string; } = action;
// if the poll doesn't exist
if (!(pollId in state.polls)) {

View File

@ -34,7 +34,6 @@ export type Poll = {
*/
changingVote: boolean,
/**
* The last sent votes for this poll, or null if voting was skipped
* Note: This is reset when voting/skipping, not when clicking "Change vote".

View File

@ -1,17 +1,22 @@
// @flow
// @ts-ignore
import { Transport } from '../../../modules/transport';
import { ReducerRegistry, set } from '../base/redux';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import { set } from '../base/redux/functions';
import {
SET_TRANSPORT,
SUSPEND_DETECTED
} from './actionTypes';
export interface IPowerMonitorState {
suspendDetected?: boolean;
transport?: Transport;
}
/**
* Reduces the redux actions of the feature power monitor.
*/
ReducerRegistry.register('features/power-monitor', (state = { }, action) => {
ReducerRegistry.register('features/power-monitor', (state: IPowerMonitorState = { }, action) => {
switch (action.type) {
case SET_TRANSPORT:
return _setTransport(state, action.transport);
@ -33,7 +38,7 @@ ReducerRegistry.register('features/power-monitor', (state = { }, action) => {
* @returns {Object} The new state of the feature power monitor after the reduction of
* the specified action.
*/
function _setTransport(state, transport: ?Transport) {
function _setTransport(state: IPowerMonitorState, transport?: Transport) {
return set(state, 'transport', transport);
}
@ -45,7 +50,7 @@ function _setTransport(state, transport: ?Transport) {
* @returns {Object} The new state of the feature overlay after the reduction of
* the specified action.
*/
function _suspendDetected(state) {
function _suspendDetected(state: IPowerMonitorState) {
return set(state, 'suspendDetected', true);
}

View File

@ -1,4 +1,5 @@
import { PersistenceRegistry, ReducerRegistry } from '../base/redux';
import PersistenceRegistry from '../base/redux/PersistenceRegistry';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import {
PREJOIN_JOINING_IN_PROGRESS,
@ -33,16 +34,31 @@ const DEFAULT_STATE = {
showJoinByPhoneDialog: false
};
/**
* The name of the redux store/state property which is the root of the redux
* state of the feature {@code prejoin}.
*/
const STORE_NAME = 'features/prejoin';
export interface IPrejoinState {
country: string;
deviceStatusText: string;
deviceStatusType: string;
dialOutCountry: {
code: string;
dialCode: string;
name: string;
};
dialOutNumber: string;
dialOutStatus: string;
isDisplayNameRequired: boolean;
joiningInProgress?: boolean;
name: string;
precallTestResults?: Object;
rawError: string;
showJoinByPhoneDialog: boolean;
showPrejoin: boolean;
skipPrejoinOnReload: boolean;
}
/**
* Sets up the persistence of the feature {@code prejoin}.
*/
PersistenceRegistry.register(STORE_NAME, {
PersistenceRegistry.register('features/prejoin', {
skipPrejoinOnReload: true
}, DEFAULT_STATE);
@ -50,7 +66,7 @@ PersistenceRegistry.register(STORE_NAME, {
* Listen for actions that mutate the prejoin state.
*/
ReducerRegistry.register(
'features/prejoin', (state = DEFAULT_STATE, action) => {
'features/prejoin', (state: IPrejoinState = DEFAULT_STATE, action) => {
switch (action.type) {
case PREJOIN_JOINING_IN_PROGRESS:
return {
@ -142,7 +158,11 @@ ReducerRegistry.register(
* @param {Object} errors - The errors got while creating local tracks.
* @returns {Object}
*/
function getStatusFromErrors(errors) {
function getStatusFromErrors(errors: {
audioAndVideoError?: {message: string},
audioOnlyError?: { message: string },
videoOnlyError?: Object }
) {
const { audioOnlyError, videoOnlyError, audioAndVideoError } = errors;
if (audioAndVideoError) {

View File

@ -9,7 +9,7 @@ import {
} from './actionTypes';
import { ReactionEmojiProps } from './constants';
interface IReactionsState {
export interface IReactionsState {
/**
* An array that contains the reactions buffer to be sent.