Files
jitsi-meet/react/features/base/connection/reducer.ts
Дамян Минков 4ee613ed1f fix(visitors): Fixes going live when the meeting is created. (#14905)
* fix(visitors): Fixes going live when first moderator joins.

* squash(jwt): Drop unused field.

* squash(jwt): Fixes loading token_util for visitors component.

* squash(jwt): Validate nbf if it exists as it is optional.

* squash(visitors): Keep prefer visitor state for not live meetings.

* squash(visitors): Automatically go live only when there is a moderator in the meeting.

* squash(visitors): Automatically go live only when there is an occupant in the meeting.

* squash(visitors): Drops a debug log.

* squash(visitors): Makes sure we first disconnect before attempting a reconnect.

If the reconnect happens too quickly, before being disconnected and the conference is still not live we will detect that we are still connected and will skip connecting to visitors service, and in the next moment we will disconnect.

* squash(visitors): Slow down successful reconnects.

If a meeting was just live but was destroyed jicofo will return it is not live, but service will return that it just got live. Slows down reconnects and at some point the service will return that the meeting is not live. The drawback is that it will take some time to connect when the meeting is created and back live.

* squash(visitors): Randomize the delay up to the available value.
2024-07-11 08:42:49 -05:00

270 lines
8.2 KiB
TypeScript

import { SET_ROOM } from '../conference/actionTypes';
import { SET_JWT } from '../jwt/actionTypes';
import { JitsiConnectionErrors } from '../lib-jitsi-meet';
import ReducerRegistry from '../redux/ReducerRegistry';
import { assign, set } from '../redux/functions';
import {
CONNECTION_DISCONNECTED,
CONNECTION_ESTABLISHED,
CONNECTION_FAILED,
CONNECTION_WILL_CONNECT,
SET_LOCATION_URL,
SET_PREFER_VISITOR,
SHOW_CONNECTION_INFO
} from './actionTypes';
import { ConnectionFailedError } from './types';
export interface IConnectionState {
connecting?: any;
connection?: {
addFeature: Function;
disconnect: Function;
getJid: () => string;
getLogs: () => Object;
initJitsiConference: Function;
removeFeature: Function;
};
error?: ConnectionFailedError;
locationURL?: URL;
passwordRequired?: Object;
preferVisitor?: boolean;
showConnectionInfo?: boolean;
timeEstablished?: number;
}
/**
* Reduces the Redux actions of the feature base/connection.
*/
ReducerRegistry.register<IConnectionState>(
'features/base/connection',
(state = {}, action): IConnectionState => {
switch (action.type) {
case CONNECTION_DISCONNECTED:
return _connectionDisconnected(state, action);
case CONNECTION_ESTABLISHED:
return _connectionEstablished(state, action);
case CONNECTION_FAILED:
return _connectionFailed(state, action);
case CONNECTION_WILL_CONNECT:
return _connectionWillConnect(state, action);
case SET_JWT:
return _setJWT(state, action);
case SET_LOCATION_URL:
return _setLocationURL(state, action);
case SET_PREFER_VISITOR:
return assign(state, {
preferVisitor: action.preferVisitor
});
case SET_ROOM:
return _setRoom(state);
case SHOW_CONNECTION_INFO:
return _setShowConnectionInfo(state, action);
}
return state;
});
/**
* Reduces a specific Redux action CONNECTION_DISCONNECTED of the feature
* base/connection.
*
* @param {IConnectionState} state - The Redux state of the feature base/connection.
* @param {Action} action - The Redux action CONNECTION_DISCONNECTED to reduce.
* @private
* @returns {Object} The new state of the feature base/connection after the
* reduction of the specified action.
*/
function _connectionDisconnected(
state: IConnectionState,
{ connection }: { connection: Object; }) {
const connection_ = _getCurrentConnection(state);
if (connection_ !== connection) {
return state;
}
return assign(state, {
connecting: undefined,
connection: undefined,
preferVisitor: undefined,
timeEstablished: undefined
});
}
/**
* Reduces a specific Redux action CONNECTION_ESTABLISHED of the feature
* base/connection.
*
* @param {IConnectionState} state - The Redux state of the feature base/connection.
* @param {Action} action - The Redux action CONNECTION_ESTABLISHED to reduce.
* @private
* @returns {Object} The new state of the feature base/connection after the
* reduction of the specified action.
*/
function _connectionEstablished(
state: IConnectionState,
{ connection, timeEstablished }: {
connection: any;
timeEstablished: number;
}) {
return assign(state, {
connecting: undefined,
connection,
error: undefined,
passwordRequired: undefined,
timeEstablished
});
}
/**
* Reduces a specific Redux action CONNECTION_FAILED of the feature
* base/connection.
*
* @param {IConnectionState} state - The Redux state of the feature base/connection.
* @param {Action} action - The Redux action CONNECTION_FAILED to reduce.
* @private
* @returns {Object} The new state of the feature base/connection after the
* reduction of the specified action.
*/
function _connectionFailed(
state: IConnectionState,
{ connection, error }: {
connection: Object;
error: ConnectionFailedError;
}) {
const connection_ = _getCurrentConnection(state);
if (connection_ && connection_ !== connection) {
return state;
}
let preferVisitor;
if (error.name === JitsiConnectionErrors.NOT_LIVE_ERROR) {
// we want to keep the state for the moment when the meeting is live
preferVisitor = state.preferVisitor;
}
return assign(state, {
connecting: undefined,
connection: undefined,
error,
passwordRequired:
error.name === JitsiConnectionErrors.PASSWORD_REQUIRED
? connection : undefined,
preferVisitor
});
}
/**
* Reduces a specific Redux action CONNECTION_WILL_CONNECT of the feature
* base/connection.
*
* @param {IConnectionState} state - The Redux state of the feature base/connection.
* @param {Action} action - The Redux action CONNECTION_WILL_CONNECT to reduce.
* @private
* @returns {Object} The new state of the feature base/connection after the
* reduction of the specified action.
*/
function _connectionWillConnect(
state: IConnectionState,
{ connection }: { connection: Object; }) {
return assign(state, {
connecting: connection,
// We don't care if the previous connection has been closed already,
// because it's an async process and there's no guarantee if it'll be
// done before the new one is established.
connection: undefined,
error: undefined,
passwordRequired: undefined,
timeEstablished: undefined
});
}
/**
* The current (similar to getCurrentConference in base/conference/functions.any.js)
* connection which is {@code connection} or {@code connecting}.
*
* @param {IConnectionState} baseConnectionState - The current state of the
* {@code 'base/connection'} feature.
* @returns {JitsiConnection} - The current {@code JitsiConnection} if any.
* @private
*/
function _getCurrentConnection(baseConnectionState: IConnectionState): IConnectionState | undefined {
return baseConnectionState.connection || baseConnectionState.connecting;
}
/**
* Reduces a specific redux action {@link SET_JWT} of the feature
* base/connection.
*
* @param {IConnectionState} state - The redux state of the feature base/connection.
* @param {Action} action - The Redux action SET_JWT to reduce.
* @private
* @returns {Object} The new state of the feature base/connection after the
* reduction of the specified action.
*/
function _setJWT(state: IConnectionState, { preferVisitor }: { preferVisitor: boolean; }) {
return assign(state, {
preferVisitor
});
}
/**
* Reduces a specific redux action {@link SET_LOCATION_URL} of the feature
* base/connection.
*
* @param {IConnectionState} state - The redux state of the feature base/connection.
* @param {Action} action - The redux action {@code SET_LOCATION_URL} to reduce.
* @private
* @returns {Object} The new state of the feature base/connection after the
* reduction of the specified action.
*/
function _setLocationURL(
state: IConnectionState,
{ locationURL }: { locationURL?: URL; }) {
return set(state, 'locationURL', locationURL);
}
/**
* Reduces a specific redux action {@link SET_ROOM} of the feature
* base/connection.
*
* @param {IConnectionState} state - The redux state of the feature base/connection.
* @private
* @returns {Object} The new state of the feature base/connection after the
* reduction of the specified action.
*/
function _setRoom(state: IConnectionState) {
return assign(state, {
error: undefined,
passwordRequired: undefined
});
}
/**
* Reduces a specific redux action {@link SHOW_CONNECTION_INFO} of the feature
* base/connection.
*
* @param {IConnectionState} state - The redux state of the feature base/connection.
* @param {Action} action - The redux action {@code SHOW_CONNECTION_INFO} to reduce.
* @private
* @returns {Object} The new state of the feature base/connection after the
* reduction of the specified action.
*/
function _setShowConnectionInfo(
state: IConnectionState,
{ showConnectionInfo }: { showConnectionInfo: boolean; }) {
return set(state, 'showConnectionInfo', showConnectionInfo);
}