2022-09-21 08:32:50 +00:00
|
|
|
import { IStore } from '../../app/types';
|
2022-09-06 17:32:20 +00:00
|
|
|
import { showNotification } from '../../notifications/actions';
|
|
|
|
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
|
2022-08-08 08:12:22 +00:00
|
|
|
import { set } from '../redux/functions';
|
2017-11-21 17:38:40 +00:00
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
import {
|
|
|
|
DOMINANT_SPEAKER_CHANGED,
|
2018-07-26 16:33:40 +00:00
|
|
|
HIDDEN_PARTICIPANT_JOINED,
|
|
|
|
HIDDEN_PARTICIPANT_LEFT,
|
2020-07-15 10:13:28 +00:00
|
|
|
GRANT_MODERATOR,
|
2017-08-14 15:02:58 +00:00
|
|
|
KICK_PARTICIPANT,
|
2022-01-21 08:07:55 +00:00
|
|
|
LOCAL_PARTICIPANT_AUDIO_LEVEL_CHANGED,
|
2021-06-23 11:23:44 +00:00
|
|
|
LOCAL_PARTICIPANT_RAISE_HAND,
|
2017-08-14 15:02:58 +00:00
|
|
|
MUTE_REMOTE_PARTICIPANT,
|
2022-06-03 11:45:27 +00:00
|
|
|
OVERWRITE_PARTICIPANT_NAME,
|
|
|
|
OVERWRITE_PARTICIPANTS_NAMES,
|
2016-10-05 14:36:59 +00:00
|
|
|
PARTICIPANT_ID_CHANGED,
|
|
|
|
PARTICIPANT_JOINED,
|
2019-06-28 22:22:43 +00:00
|
|
|
PARTICIPANT_KICKED,
|
2016-10-05 14:36:59 +00:00
|
|
|
PARTICIPANT_LEFT,
|
|
|
|
PARTICIPANT_UPDATED,
|
2019-06-26 14:08:23 +00:00
|
|
|
PIN_PARTICIPANT,
|
2022-06-03 11:45:27 +00:00
|
|
|
RAISE_HAND_UPDATED,
|
2022-04-14 17:07:17 +00:00
|
|
|
SCREENSHARE_PARTICIPANT_NAME_CHANGED,
|
2021-09-10 11:05:16 +00:00
|
|
|
SET_LOADABLE_AVATAR_URL,
|
2022-06-03 11:45:27 +00:00
|
|
|
SET_LOCAL_PARTICIPANT_RECORDING_STATUS
|
2016-10-05 14:36:59 +00:00
|
|
|
} from './actionTypes';
|
2021-02-24 21:45:07 +00:00
|
|
|
import {
|
|
|
|
DISCO_REMOTE_CONTROL_FEATURE
|
|
|
|
} from './constants';
|
2019-06-17 14:00:09 +00:00
|
|
|
import {
|
|
|
|
getLocalParticipant,
|
2022-04-29 14:32:16 +00:00
|
|
|
getVirtualScreenshareParticipantOwnerId,
|
2019-06-17 14:00:09 +00:00
|
|
|
getNormalizedDisplayName,
|
2020-11-14 04:09:25 +00:00
|
|
|
getParticipantDisplayName,
|
|
|
|
getParticipantById
|
2019-06-17 14:00:09 +00:00
|
|
|
} from './functions';
|
2020-11-14 04:09:25 +00:00
|
|
|
import logger from './logger';
|
2022-09-06 17:32:20 +00:00
|
|
|
import { Participant } from './types';
|
2016-10-05 14:36:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create an action for when dominant speaker changes.
|
|
|
|
*
|
2021-08-18 22:34:01 +00:00
|
|
|
* @param {string} dominantSpeaker - Participant ID of the dominant speaker.
|
|
|
|
* @param {Array<string>} previousSpeakers - Participant IDs of the previous speakers.
|
2022-09-08 21:14:00 +00:00
|
|
|
* @param {boolean} silence - Whether the dominant speaker is silent or not.
|
Associate remote participant w/ JitsiConference (_UPDATED)
The commit message of "Associate remote participant w/ JitsiConference
(_JOINED)" explains the motivation for this commit.
Practically, _JOINED and _LEFT combined with "Remove remote participants
who are no longer of interest" should alleviate the problem with
multiplying remote participants to an acceptable level of annoyance.
Technically though, a remote participant cannot be identified by an ID
only. The ID is (somewhat) "unique" in the context of a single
JitsiConference instance. So in order to not have to scratch our heads
over an obscure corner, racing case, it's better to always identify
remote participants by the pair id-conference. Unfortunately, that's a
bit of a high order given the existing source code. So I've implemented
the cases which are the easiest so that new source code written with
participantUpdated is more likely to identify a remote participant with
the pair id-conference.
Additionally, the commit "Reduce direct read access to the
features/base/participants redux state" brings more control back to the
functions of the feature base/participants so that one day we can (if we
choose to) do something like, for example:
If getParticipants is called with a conference, it returns the
participants from features/base/participants who are associated with the
specified conference. If no conference is specified in the function
call, then default to the conference which is the primary focus of the
app at the time of the function call. Added to the above, this should
allow us to further reduce the cases in which we're identifying remote
participants by id only and get us even closer to a more "predictable"
behavior in corner, racing cases.
2018-05-22 21:47:43 +00:00
|
|
|
* @param {JitsiConference} conference - The {@code JitsiConference} associated
|
|
|
|
* with the participant identified by the specified {@code id}. Only the local
|
|
|
|
* participant is allowed to not specify an associated {@code JitsiConference}
|
|
|
|
* instance.
|
2016-10-05 14:36:59 +00:00
|
|
|
* @returns {{
|
2017-03-07 16:50:17 +00:00
|
|
|
* type: DOMINANT_SPEAKER_CHANGED,
|
|
|
|
* participant: {
|
Associate remote participant w/ JitsiConference (_UPDATED)
The commit message of "Associate remote participant w/ JitsiConference
(_JOINED)" explains the motivation for this commit.
Practically, _JOINED and _LEFT combined with "Remove remote participants
who are no longer of interest" should alleviate the problem with
multiplying remote participants to an acceptable level of annoyance.
Technically though, a remote participant cannot be identified by an ID
only. The ID is (somewhat) "unique" in the context of a single
JitsiConference instance. So in order to not have to scratch our heads
over an obscure corner, racing case, it's better to always identify
remote participants by the pair id-conference. Unfortunately, that's a
bit of a high order given the existing source code. So I've implemented
the cases which are the easiest so that new source code written with
participantUpdated is more likely to identify a remote participant with
the pair id-conference.
Additionally, the commit "Reduce direct read access to the
features/base/participants redux state" brings more control back to the
functions of the feature base/participants so that one day we can (if we
choose to) do something like, for example:
If getParticipants is called with a conference, it returns the
participants from features/base/participants who are associated with the
specified conference. If no conference is specified in the function
call, then default to the conference which is the primary focus of the
app at the time of the function call. Added to the above, this should
allow us to further reduce the cases in which we're identifying remote
participants by id only and get us even closer to a more "predictable"
behavior in corner, racing cases.
2018-05-22 21:47:43 +00:00
|
|
|
* conference: JitsiConference,
|
2021-08-18 22:34:01 +00:00
|
|
|
* id: string,
|
2022-09-08 21:14:00 +00:00
|
|
|
* previousSpeakers: Array<string>,
|
|
|
|
* silence: boolean
|
2017-03-07 16:50:17 +00:00
|
|
|
* }
|
2016-10-05 14:36:59 +00:00
|
|
|
* }}
|
|
|
|
*/
|
2022-09-08 21:14:00 +00:00
|
|
|
export function dominantSpeakerChanged(
|
|
|
|
dominantSpeaker: string, previousSpeakers: string[], silence: boolean, conference: any) {
|
2016-10-05 14:36:59 +00:00
|
|
|
return {
|
|
|
|
type: DOMINANT_SPEAKER_CHANGED,
|
|
|
|
participant: {
|
Associate remote participant w/ JitsiConference (_UPDATED)
The commit message of "Associate remote participant w/ JitsiConference
(_JOINED)" explains the motivation for this commit.
Practically, _JOINED and _LEFT combined with "Remove remote participants
who are no longer of interest" should alleviate the problem with
multiplying remote participants to an acceptable level of annoyance.
Technically though, a remote participant cannot be identified by an ID
only. The ID is (somewhat) "unique" in the context of a single
JitsiConference instance. So in order to not have to scratch our heads
over an obscure corner, racing case, it's better to always identify
remote participants by the pair id-conference. Unfortunately, that's a
bit of a high order given the existing source code. So I've implemented
the cases which are the easiest so that new source code written with
participantUpdated is more likely to identify a remote participant with
the pair id-conference.
Additionally, the commit "Reduce direct read access to the
features/base/participants redux state" brings more control back to the
functions of the feature base/participants so that one day we can (if we
choose to) do something like, for example:
If getParticipants is called with a conference, it returns the
participants from features/base/participants who are associated with the
specified conference. If no conference is specified in the function
call, then default to the conference which is the primary focus of the
app at the time of the function call. Added to the above, this should
allow us to further reduce the cases in which we're identifying remote
participants by id only and get us even closer to a more "predictable"
behavior in corner, racing cases.
2018-05-22 21:47:43 +00:00
|
|
|
conference,
|
2021-08-18 22:34:01 +00:00
|
|
|
id: dominantSpeaker,
|
2022-09-08 21:14:00 +00:00
|
|
|
previousSpeakers,
|
|
|
|
silence
|
2016-10-05 14:36:59 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-07-15 10:13:28 +00:00
|
|
|
/**
|
|
|
|
* Create an action for granting moderator to a participant.
|
|
|
|
*
|
|
|
|
* @param {string} id - Participant's ID.
|
|
|
|
* @returns {{
|
|
|
|
* type: GRANT_MODERATOR,
|
|
|
|
* id: string
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function grantModerator(id: string) {
|
2020-07-15 10:13:28 +00:00
|
|
|
return {
|
|
|
|
type: GRANT_MODERATOR,
|
|
|
|
id
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-10-09 15:03:02 +00:00
|
|
|
/**
|
|
|
|
* Create an action for removing a participant from the conference.
|
|
|
|
*
|
|
|
|
* @param {string} id - Participant's ID.
|
|
|
|
* @returns {{
|
|
|
|
* type: KICK_PARTICIPANT,
|
|
|
|
* id: string
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function kickParticipant(id: string) {
|
2017-10-09 15:03:02 +00:00
|
|
|
return {
|
|
|
|
type: KICK_PARTICIPANT,
|
|
|
|
id
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-07-13 00:26:10 +00:00
|
|
|
/**
|
|
|
|
* Creates an action to signal the connection status of the local participant
|
|
|
|
* has changed.
|
|
|
|
*
|
|
|
|
* @param {string} connectionStatus - The current connection status of the local
|
|
|
|
* participant, as enumerated by the library's participantConnectionStatus
|
|
|
|
* constants.
|
|
|
|
* @returns {Function}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function localParticipantConnectionStatusChanged(connectionStatus: string) {
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2017-07-13 00:26:10 +00:00
|
|
|
const participant = getLocalParticipant(getState);
|
|
|
|
|
|
|
|
if (participant) {
|
|
|
|
return dispatch(participantConnectionStatusChanged(
|
2017-10-09 15:03:02 +00:00
|
|
|
participant.id,
|
|
|
|
connectionStatus));
|
2017-07-13 00:26:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
2017-04-10 21:53:30 +00:00
|
|
|
* Action to signal that the ID of local participant has changed. It happens
|
|
|
|
* when the local participant joins a new conference or leaves an existing
|
|
|
|
* conference.
|
2016-10-05 14:36:59 +00:00
|
|
|
*
|
|
|
|
* @param {string} id - New ID for local participant.
|
2017-04-10 21:53:30 +00:00
|
|
|
* @returns {Function}
|
2016-10-05 14:36:59 +00:00
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function localParticipantIdChanged(id: string) {
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2016-10-05 14:36:59 +00:00
|
|
|
const participant = getLocalParticipant(getState);
|
|
|
|
|
|
|
|
if (participant) {
|
|
|
|
return dispatch({
|
|
|
|
type: PARTICIPANT_ID_CHANGED,
|
2018-05-27 20:42:13 +00:00
|
|
|
|
|
|
|
// XXX A participant is identified by an id-conference pair.
|
|
|
|
// Only the local participant is with an undefined conference.
|
|
|
|
conference: undefined,
|
2016-10-05 14:36:59 +00:00
|
|
|
newValue: id,
|
|
|
|
oldValue: participant.id
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Action to signal that a local participant has joined.
|
|
|
|
*
|
|
|
|
* @param {Participant} participant={} - Information about participant.
|
|
|
|
* @returns {{
|
2017-03-07 16:50:17 +00:00
|
|
|
* type: PARTICIPANT_JOINED,
|
|
|
|
* participant: Participant
|
2016-10-05 14:36:59 +00:00
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function localParticipantJoined(participant: Participant = { id: '' }) {
|
2018-05-29 01:43:28 +00:00
|
|
|
return participantJoined(set(participant, 'local', true));
|
2016-10-05 14:36:59 +00:00
|
|
|
}
|
|
|
|
|
2017-10-09 15:03:02 +00:00
|
|
|
/**
|
|
|
|
* Action to remove a local participant.
|
|
|
|
*
|
|
|
|
* @returns {Function}
|
|
|
|
*/
|
|
|
|
export function localParticipantLeft() {
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2017-10-09 15:03:02 +00:00
|
|
|
const participant = getLocalParticipant(getState);
|
|
|
|
|
|
|
|
if (participant) {
|
2018-05-22 21:08:35 +00:00
|
|
|
return (
|
|
|
|
dispatch(
|
|
|
|
participantLeft(
|
|
|
|
participant.id,
|
|
|
|
|
|
|
|
// XXX Only the local participant is allowed to leave
|
|
|
|
// without stating the JitsiConference instance because
|
|
|
|
// the local participant is uniquely identified by the
|
|
|
|
// very fact that there is only one local participant
|
|
|
|
// (and the fact that the local participant "joins" at
|
|
|
|
// the beginning of the app and "leaves" at the end of
|
|
|
|
// the app).
|
|
|
|
undefined)));
|
2017-10-09 15:03:02 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-04-10 21:53:30 +00:00
|
|
|
/**
|
|
|
|
* Action to signal the role of the local participant has changed. It can happen
|
|
|
|
* when the participant has joined a conference, even before a non-default local
|
|
|
|
* id has been set, or after a moderator leaves.
|
|
|
|
*
|
|
|
|
* @param {string} role - The new role of the local participant.
|
|
|
|
* @returns {Function}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function localParticipantRoleChanged(role: string) {
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2017-04-10 21:53:30 +00:00
|
|
|
const participant = getLocalParticipant(getState);
|
|
|
|
|
|
|
|
if (participant) {
|
|
|
|
return dispatch(participantRoleChanged(participant.id, role));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-08-14 15:02:58 +00:00
|
|
|
/**
|
|
|
|
* Create an action for muting another participant in the conference.
|
|
|
|
*
|
|
|
|
* @param {string} id - Participant's ID.
|
2021-02-24 21:45:07 +00:00
|
|
|
* @param {MEDIA_TYPE} mediaType - The media to mute.
|
2017-08-14 15:02:58 +00:00
|
|
|
* @returns {{
|
|
|
|
* type: MUTE_REMOTE_PARTICIPANT,
|
2021-02-24 21:45:07 +00:00
|
|
|
* id: string,
|
|
|
|
* mediaType: MEDIA_TYPE
|
2017-08-14 15:02:58 +00:00
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function muteRemoteParticipant(id: string, mediaType: string) {
|
2017-08-14 15:02:58 +00:00
|
|
|
return {
|
|
|
|
type: MUTE_REMOTE_PARTICIPANT,
|
2021-02-24 21:45:07 +00:00
|
|
|
id,
|
|
|
|
mediaType
|
2017-08-14 15:02:58 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-04-05 09:01:57 +00:00
|
|
|
/**
|
|
|
|
* Action to update a participant's connection status.
|
|
|
|
*
|
|
|
|
* @param {string} id - Participant's ID.
|
|
|
|
* @param {string} connectionStatus - The new connection status of the
|
|
|
|
* participant.
|
|
|
|
* @returns {{
|
|
|
|
* type: PARTICIPANT_UPDATED,
|
|
|
|
* participant: {
|
|
|
|
* connectionStatus: string,
|
|
|
|
* id: string
|
|
|
|
* }
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function participantConnectionStatusChanged(id: string, connectionStatus: string) {
|
2020-12-14 21:38:29 +00:00
|
|
|
return {
|
|
|
|
type: PARTICIPANT_UPDATED,
|
|
|
|
participant: {
|
|
|
|
connectionStatus,
|
|
|
|
id
|
|
|
|
}
|
2017-04-05 09:01:57 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
|
|
|
* Action to signal that a participant has joined.
|
|
|
|
*
|
|
|
|
* @param {Participant} participant - Information about participant.
|
|
|
|
* @returns {{
|
2018-05-22 19:30:51 +00:00
|
|
|
* type: PARTICIPANT_JOINED,
|
|
|
|
* participant: Participant
|
2016-10-05 14:36:59 +00:00
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function participantJoined(participant: Participant) {
|
2018-05-28 00:13:26 +00:00
|
|
|
// Only the local participant is not identified with an id-conference pair.
|
|
|
|
if (participant.local) {
|
|
|
|
return {
|
|
|
|
type: PARTICIPANT_JOINED,
|
|
|
|
participant
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// In other words, a remote participant is identified with an id-conference
|
|
|
|
// pair.
|
|
|
|
const { conference } = participant;
|
|
|
|
|
|
|
|
if (!conference) {
|
2018-05-22 19:30:51 +00:00
|
|
|
throw Error(
|
|
|
|
'A remote participant must be associated with a JitsiConference!');
|
|
|
|
}
|
|
|
|
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2018-05-28 00:13:26 +00:00
|
|
|
// A remote participant is only expected to join in a joined or joining
|
|
|
|
// conference. The following check is really necessary because a
|
|
|
|
// JitsiConference may have moved into leaving but may still manage to
|
|
|
|
// sneak a PARTICIPANT_JOINED in if its leave is delayed for any purpose
|
|
|
|
// (which is not outragous given that leaving involves network
|
|
|
|
// requests.)
|
|
|
|
const stateFeaturesBaseConference
|
|
|
|
= getState()['features/base/conference'];
|
|
|
|
|
|
|
|
if (conference === stateFeaturesBaseConference.conference
|
|
|
|
|| conference === stateFeaturesBaseConference.joining) {
|
|
|
|
return dispatch({
|
|
|
|
type: PARTICIPANT_JOINED,
|
|
|
|
participant
|
|
|
|
});
|
|
|
|
}
|
2016-10-05 14:36:59 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-11-14 04:09:25 +00:00
|
|
|
/**
|
|
|
|
* Updates the features of a remote participant.
|
|
|
|
*
|
|
|
|
* @param {JitsiParticipant} jitsiParticipant - The ID of the participant.
|
|
|
|
* @returns {{
|
|
|
|
* type: PARTICIPANT_UPDATED,
|
|
|
|
* participant: Participant
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function updateRemoteParticipantFeatures(jitsiParticipant: any) {
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2020-11-14 04:09:25 +00:00
|
|
|
if (!jitsiParticipant) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const id = jitsiParticipant.getId();
|
|
|
|
|
|
|
|
jitsiParticipant.getFeatures()
|
2022-08-08 08:12:22 +00:00
|
|
|
.then((features: Map<string, string>) => {
|
2020-11-14 04:09:25 +00:00
|
|
|
const supportsRemoteControl = features.has(DISCO_REMOTE_CONTROL_FEATURE);
|
|
|
|
const participant = getParticipantById(getState(), id);
|
|
|
|
|
|
|
|
if (!participant || participant.local) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (participant?.supportsRemoteControl !== supportsRemoteControl) {
|
|
|
|
return dispatch({
|
|
|
|
type: PARTICIPANT_UPDATED,
|
|
|
|
participant: {
|
|
|
|
id,
|
|
|
|
supportsRemoteControl
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})
|
2022-08-08 08:12:22 +00:00
|
|
|
.catch((error: any) => {
|
2020-11-14 04:09:25 +00:00
|
|
|
logger.error(`Failed to get participant features for ${id}!`, error);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-07-26 16:33:40 +00:00
|
|
|
/**
|
|
|
|
* Action to signal that a hidden participant has joined the conference.
|
|
|
|
*
|
|
|
|
* @param {string} id - The id of the participant.
|
|
|
|
* @param {string} displayName - The display name, or undefined when
|
|
|
|
* unknown.
|
|
|
|
* @returns {{
|
|
|
|
* type: HIDDEN_PARTICIPANT_JOINED,
|
|
|
|
* displayName: string,
|
|
|
|
* id: string
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function hiddenParticipantJoined(id: string, displayName: string) {
|
2018-07-26 16:33:40 +00:00
|
|
|
return {
|
|
|
|
type: HIDDEN_PARTICIPANT_JOINED,
|
|
|
|
id,
|
|
|
|
displayName
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Action to signal that a hidden participant has left the conference.
|
|
|
|
*
|
|
|
|
* @param {string} id - The id of the participant.
|
|
|
|
* @returns {{
|
|
|
|
* type: HIDDEN_PARTICIPANT_LEFT,
|
|
|
|
* id: string
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function hiddenParticipantLeft(id: string) {
|
2018-07-26 16:33:40 +00:00
|
|
|
return {
|
|
|
|
type: HIDDEN_PARTICIPANT_LEFT,
|
|
|
|
id
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
2017-03-07 16:50:17 +00:00
|
|
|
* Action to signal that a participant has left.
|
2016-10-05 14:36:59 +00:00
|
|
|
*
|
2017-03-07 16:50:17 +00:00
|
|
|
* @param {string} id - Participant's ID.
|
2018-05-22 21:08:35 +00:00
|
|
|
* @param {JitsiConference} conference - The {@code JitsiConference} associated
|
|
|
|
* with the participant identified by the specified {@code id}. Only the local
|
|
|
|
* participant is allowed to not specify an associated {@code JitsiConference}
|
|
|
|
* instance.
|
2022-09-06 06:51:38 +00:00
|
|
|
* @param {Object} participantLeftProps - Other participant properties.
|
|
|
|
* @typedef {Object} participantLeftProps
|
|
|
|
* @param {boolean} participantLeftProps.isReplaced - Whether the participant is to be replaced in the meeting.
|
|
|
|
* @param {boolean} participantLeftProps.isVirtualScreenshareParticipant - Whether the participant is a
|
|
|
|
* virtual screen share participant.
|
|
|
|
* @param {boolean} participantLeftProps.isFakeParticipant - Whether the participant is a fake participant.
|
|
|
|
*
|
2016-10-05 14:36:59 +00:00
|
|
|
* @returns {{
|
2017-03-07 16:50:17 +00:00
|
|
|
* type: PARTICIPANT_LEFT,
|
|
|
|
* participant: {
|
2018-05-22 21:08:35 +00:00
|
|
|
* conference: JitsiConference,
|
2017-03-07 16:50:17 +00:00
|
|
|
* id: string
|
|
|
|
* }
|
2016-10-05 14:36:59 +00:00
|
|
|
* }}
|
|
|
|
*/
|
2022-09-06 06:51:38 +00:00
|
|
|
export function participantLeft(id: string, conference: any, participantLeftProps: any = {}) {
|
2016-10-05 14:36:59 +00:00
|
|
|
return {
|
|
|
|
type: PARTICIPANT_LEFT,
|
|
|
|
participant: {
|
2018-05-22 21:08:35 +00:00
|
|
|
conference,
|
2021-06-11 08:58:45 +00:00
|
|
|
id,
|
2022-09-06 06:51:38 +00:00
|
|
|
isReplaced: participantLeftProps.isReplaced,
|
|
|
|
isVirtualScreenshareParticipant: participantLeftProps.isVirtualScreenshareParticipant,
|
|
|
|
isFakeParticipant: participantLeftProps.isFakeParticipant
|
2016-10-05 14:36:59 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-07-31 23:33:22 +00:00
|
|
|
/**
|
|
|
|
* Action to signal that a participant's presence status has changed.
|
|
|
|
*
|
|
|
|
* @param {string} id - Participant's ID.
|
|
|
|
* @param {string} presence - Participant's new presence status.
|
|
|
|
* @returns {{
|
|
|
|
* type: PARTICIPANT_UPDATED,
|
|
|
|
* participant: {
|
|
|
|
* id: string,
|
|
|
|
* presence: string
|
|
|
|
* }
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function participantPresenceChanged(id: string, presence: string) {
|
2017-07-31 23:33:22 +00:00
|
|
|
return participantUpdated({
|
|
|
|
id,
|
|
|
|
presence
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
2017-03-07 16:50:17 +00:00
|
|
|
* Action to signal that a participant's role has changed.
|
2016-10-05 14:36:59 +00:00
|
|
|
*
|
2017-03-07 16:50:17 +00:00
|
|
|
* @param {string} id - Participant's ID.
|
2016-10-05 14:36:59 +00:00
|
|
|
* @param {PARTICIPANT_ROLE} role - Participant's new role.
|
|
|
|
* @returns {{
|
2017-03-07 16:50:17 +00:00
|
|
|
* type: PARTICIPANT_UPDATED,
|
|
|
|
* participant: {
|
|
|
|
* id: string,
|
|
|
|
* role: PARTICIPANT_ROLE
|
|
|
|
* }
|
2016-10-05 14:36:59 +00:00
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function participantRoleChanged(id: string, role: string) {
|
2017-03-23 18:01:33 +00:00
|
|
|
return participantUpdated({
|
|
|
|
id,
|
|
|
|
role
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-04-14 17:07:17 +00:00
|
|
|
/**
|
|
|
|
* Action to signal that a participant's display name has changed.
|
|
|
|
*
|
|
|
|
* @param {string} id - Screenshare participant's ID.
|
|
|
|
* @param {name} name - The new display name of the screenshare participant's owner.
|
|
|
|
* @returns {{
|
|
|
|
* type: SCREENSHARE_PARTICIPANT_NAME_CHANGED,
|
|
|
|
* id: string,
|
|
|
|
* name: string
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function screenshareParticipantDisplayNameChanged(id: string, name: string) {
|
2022-04-14 17:07:17 +00:00
|
|
|
return {
|
|
|
|
type: SCREENSHARE_PARTICIPANT_NAME_CHANGED,
|
|
|
|
id,
|
|
|
|
name
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-03-23 18:01:33 +00:00
|
|
|
/**
|
|
|
|
* Action to signal that some of participant properties has been changed.
|
|
|
|
*
|
|
|
|
* @param {Participant} participant={} - Information about participant. To
|
|
|
|
* identify the participant the object should contain either property id with
|
|
|
|
* value the id of the participant or property local with value true (if the
|
|
|
|
* local participant hasn't joined the conference yet).
|
|
|
|
* @returns {{
|
|
|
|
* type: PARTICIPANT_UPDATED,
|
|
|
|
* participant: Participant
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function participantUpdated(participant: Participant = { id: '' }) {
|
2019-01-15 11:28:07 +00:00
|
|
|
const participantToUpdate = {
|
|
|
|
...participant
|
|
|
|
};
|
|
|
|
|
2019-01-13 19:33:28 +00:00
|
|
|
if (participant.name) {
|
2019-01-15 11:28:07 +00:00
|
|
|
participantToUpdate.name = getNormalizedDisplayName(participant.name);
|
2019-01-13 19:33:28 +00:00
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
return {
|
|
|
|
type: PARTICIPANT_UPDATED,
|
2019-01-15 11:28:07 +00:00
|
|
|
participant: participantToUpdate
|
2016-10-05 14:36:59 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-06-17 14:00:09 +00:00
|
|
|
/**
|
|
|
|
* Action to signal that a participant has muted us.
|
|
|
|
*
|
|
|
|
* @param {JitsiParticipant} participant - Information about participant.
|
2021-02-24 21:45:07 +00:00
|
|
|
* @param {JitsiLocalTrack} track - Information about the track that has been muted.
|
2019-06-17 14:00:09 +00:00
|
|
|
* @returns {Promise}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function participantMutedUs(participant: any, track: any) {
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2019-06-17 14:00:09 +00:00
|
|
|
if (!participant) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-02-24 21:45:07 +00:00
|
|
|
const isAudio = track.isAudioTrack();
|
|
|
|
|
2019-06-17 14:00:09 +00:00
|
|
|
dispatch(showNotification({
|
2021-09-15 08:28:44 +00:00
|
|
|
titleKey: isAudio ? 'notify.mutedRemotelyTitle' : 'notify.videoMutedRemotelyTitle',
|
|
|
|
titleArguments: {
|
2021-10-25 07:19:09 +00:00
|
|
|
participantDisplayName: getParticipantDisplayName(getState, participant.getId())
|
2021-09-15 08:28:44 +00:00
|
|
|
}
|
2022-03-30 14:24:50 +00:00
|
|
|
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
|
2019-06-17 14:00:09 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-04-29 14:32:16 +00:00
|
|
|
/**
|
|
|
|
* Action to create a virtual screenshare participant.
|
|
|
|
*
|
|
|
|
* @param {(string)} sourceName - JitsiTrack instance.
|
|
|
|
* @param {(boolean)} local - JitsiTrack instance.
|
|
|
|
* @returns {Function}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function createVirtualScreenshareParticipant(sourceName: string, local: boolean) {
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2022-04-29 14:32:16 +00:00
|
|
|
const state = getState();
|
|
|
|
const ownerId = getVirtualScreenshareParticipantOwnerId(sourceName);
|
2022-05-19 17:31:51 +00:00
|
|
|
const ownerName = getParticipantDisplayName(state, ownerId);
|
2022-04-29 14:32:16 +00:00
|
|
|
|
|
|
|
dispatch(participantJoined({
|
|
|
|
conference: state['features/base/conference'].conference,
|
|
|
|
id: sourceName,
|
|
|
|
isVirtualScreenshareParticipant: true,
|
|
|
|
isLocalScreenShare: local,
|
|
|
|
name: ownerName
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-06-17 14:00:09 +00:00
|
|
|
/**
|
|
|
|
* Action to signal that a participant had been kicked.
|
|
|
|
*
|
|
|
|
* @param {JitsiParticipant} kicker - Information about participant performing the kick.
|
|
|
|
* @param {JitsiParticipant} kicked - Information about participant that was kicked.
|
|
|
|
* @returns {Promise}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function participantKicked(kicker: any, kicked: any) {
|
2022-09-21 08:32:50 +00:00
|
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
2019-06-17 14:00:09 +00:00
|
|
|
|
2019-06-28 22:22:43 +00:00
|
|
|
dispatch({
|
|
|
|
type: PARTICIPANT_KICKED,
|
|
|
|
kicked: kicked.getId(),
|
2021-06-11 08:58:45 +00:00
|
|
|
kicker: kicker?.getId()
|
2019-06-28 22:22:43 +00:00
|
|
|
});
|
|
|
|
|
2022-09-08 09:52:36 +00:00
|
|
|
if (kicked.isReplaced?.()) {
|
2021-06-11 08:58:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-06-17 14:00:09 +00:00
|
|
|
dispatch(showNotification({
|
|
|
|
titleArguments: {
|
|
|
|
kicked:
|
|
|
|
getParticipantDisplayName(getState, kicked.getId()),
|
|
|
|
kicker:
|
|
|
|
getParticipantDisplayName(getState, kicker.getId())
|
|
|
|
},
|
|
|
|
titleKey: 'notify.kickParticipant'
|
2021-11-24 11:05:27 +00:00
|
|
|
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
|
2019-06-17 14:00:09 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
|
|
|
* Create an action which pins a conference participant.
|
|
|
|
*
|
|
|
|
* @param {string|null} id - The ID of the conference participant to pin or null
|
|
|
|
* if none of the conference's participants are to be pinned.
|
|
|
|
* @returns {{
|
2017-03-07 16:50:17 +00:00
|
|
|
* type: PIN_PARTICIPANT,
|
|
|
|
* participant: {
|
|
|
|
* id: string
|
|
|
|
* }
|
2016-10-05 14:36:59 +00:00
|
|
|
* }}
|
|
|
|
*/
|
2022-09-08 09:52:36 +00:00
|
|
|
export function pinParticipant(id: string | null) {
|
2016-10-05 14:36:59 +00:00
|
|
|
return {
|
|
|
|
type: PIN_PARTICIPANT,
|
|
|
|
participant: {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2019-06-26 14:08:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an action which notifies the app that the loadable URL of the avatar of a participant got updated.
|
|
|
|
*
|
|
|
|
* @param {string} participantId - The ID of the participant.
|
|
|
|
* @param {string} url - The new URL.
|
2021-12-17 00:16:24 +00:00
|
|
|
* @param {boolean} useCORS - Indicates whether we need to use CORS for this URL.
|
2019-06-26 14:08:23 +00:00
|
|
|
* @returns {{
|
|
|
|
* type: SET_LOADABLE_AVATAR_URL,
|
|
|
|
* participant: {
|
|
|
|
* id: string,
|
2021-12-17 00:16:24 +00:00
|
|
|
* loadableAvatarUrl: string,
|
|
|
|
* loadableAvatarUrlUseCORS: boolean
|
2019-06-26 14:08:23 +00:00
|
|
|
* }
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function setLoadableAvatarUrl(participantId: string, url: string, useCORS: boolean) {
|
2019-06-26 14:08:23 +00:00
|
|
|
return {
|
|
|
|
type: SET_LOADABLE_AVATAR_URL,
|
|
|
|
participant: {
|
|
|
|
id: participantId,
|
2021-12-17 00:16:24 +00:00
|
|
|
loadableAvatarUrl: url,
|
|
|
|
loadableAvatarUrlUseCORS: useCORS
|
2019-06-26 14:08:23 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2020-11-14 04:09:25 +00:00
|
|
|
|
2021-06-23 11:23:44 +00:00
|
|
|
/**
|
|
|
|
* Raise hand for the local participant.
|
|
|
|
*
|
|
|
|
* @param {boolean} enabled - Raise or lower hand.
|
|
|
|
* @returns {{
|
|
|
|
* type: LOCAL_PARTICIPANT_RAISE_HAND,
|
2021-10-21 09:40:57 +00:00
|
|
|
* raisedHandTimestamp: number
|
2021-06-23 11:23:44 +00:00
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function raiseHand(enabled: boolean) {
|
2021-06-23 11:23:44 +00:00
|
|
|
return {
|
|
|
|
type: LOCAL_PARTICIPANT_RAISE_HAND,
|
2021-10-21 09:40:57 +00:00
|
|
|
raisedHandTimestamp: enabled ? Date.now() : 0
|
2021-06-23 11:23:44 +00:00
|
|
|
};
|
|
|
|
}
|
2021-09-10 11:05:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Update raise hand queue of participants.
|
|
|
|
*
|
|
|
|
* @param {Object} participant - Participant that updated raised hand.
|
|
|
|
* @returns {{
|
|
|
|
* type: RAISE_HAND_UPDATED,
|
|
|
|
* participant: Object
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function raiseHandUpdateQueue(participant: Participant) {
|
2021-09-10 11:05:16 +00:00
|
|
|
return {
|
|
|
|
type: RAISE_HAND_UPDATED,
|
|
|
|
participant
|
|
|
|
};
|
|
|
|
}
|
2022-01-21 08:07:55 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Notifies if the local participant audio level has changed.
|
|
|
|
*
|
|
|
|
* @param {number} level - The audio level.
|
|
|
|
* @returns {{
|
|
|
|
* type: LOCAL_PARTICIPANT_AUDIO_LEVEL_CHANGED,
|
|
|
|
* level: number
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function localParticipantAudioLevelChanged(level: number) {
|
2022-01-21 08:07:55 +00:00
|
|
|
return {
|
|
|
|
type: LOCAL_PARTICIPANT_AUDIO_LEVEL_CHANGED,
|
|
|
|
level
|
|
|
|
};
|
|
|
|
}
|
2022-05-20 10:45:09 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Overwrites the name of the participant with the given id.
|
|
|
|
*
|
|
|
|
* @param {string} id - Participant id;.
|
|
|
|
* @param {string} name - New participant name.
|
|
|
|
* @returns {Object}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function overwriteParticipantName(id: string, name: string) {
|
2022-05-20 10:45:09 +00:00
|
|
|
return {
|
|
|
|
type: OVERWRITE_PARTICIPANT_NAME,
|
|
|
|
id,
|
|
|
|
name
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Overwrites the names of the given participants.
|
|
|
|
*
|
|
|
|
* @param {Array<Object>} participantList - The list of participants to overwrite.
|
|
|
|
* @returns {Object}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function overwriteParticipantsNames(participantList: Participant[]) {
|
2022-05-20 10:45:09 +00:00
|
|
|
return {
|
|
|
|
type: OVERWRITE_PARTICIPANTS_NAMES,
|
|
|
|
participantList
|
|
|
|
};
|
|
|
|
}
|
2022-06-03 11:45:27 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Local video recording status for the local participant.
|
|
|
|
*
|
|
|
|
* @param {boolean} recording - If local recording is ongoing.
|
2022-06-24 12:07:40 +00:00
|
|
|
* @param {boolean} onlySelf - If recording only local streams.
|
2022-06-03 11:45:27 +00:00
|
|
|
* @returns {{
|
|
|
|
* type: SET_LOCAL_PARTICIPANT_RECORDING_STATUS,
|
|
|
|
* recording: boolean
|
|
|
|
* }}
|
|
|
|
*/
|
2022-08-08 08:12:22 +00:00
|
|
|
export function updateLocalRecordingStatus(recording: boolean, onlySelf: boolean) {
|
2022-06-03 11:45:27 +00:00
|
|
|
return {
|
|
|
|
type: SET_LOCAL_PARTICIPANT_RECORDING_STATUS,
|
2022-06-24 12:07:40 +00:00
|
|
|
recording,
|
|
|
|
onlySelf
|
2022-06-03 11:45:27 +00:00
|
|
|
};
|
|
|
|
}
|