Some checks failed
Close stale issues and PRs / stale (push) Has been cancelled
360 lines
9.4 KiB
TypeScript
360 lines
9.4 KiB
TypeScript
import { IStore } from '../app/types';
|
|
import { getCurrentConference } from '../base/conference/functions';
|
|
import { getLocalParticipant, getParticipantById } from '../base/participants/functions';
|
|
import { IParticipant } from '../base/participants/types';
|
|
import { LOBBY_CHAT_INITIALIZED } from '../lobby/constants';
|
|
|
|
import {
|
|
ADD_MESSAGE,
|
|
ADD_MESSAGE_REACTION,
|
|
CLEAR_MESSAGES,
|
|
CLOSE_CHAT,
|
|
EDIT_MESSAGE,
|
|
NOTIFY_PRIVATE_RECIPIENTS_CHANGED,
|
|
OPEN_CHAT,
|
|
REMOVE_LOBBY_CHAT_PARTICIPANT,
|
|
SEND_MESSAGE,
|
|
SEND_REACTION,
|
|
SET_FOCUSED_TAB,
|
|
SET_LOBBY_CHAT_ACTIVE_STATE,
|
|
SET_LOBBY_CHAT_RECIPIENT,
|
|
SET_PRIVATE_MESSAGE_RECIPIENT
|
|
} from './actionTypes';
|
|
import { ChatTabs } from './constants';
|
|
|
|
/**
|
|
* Adds a chat message to the collection of messages.
|
|
*
|
|
* @param {Object} messageDetails - The chat message to save.
|
|
* @param {string} messageDetails.displayName - The displayName of the
|
|
* participant that authored the message.
|
|
* @param {boolean} messageDetails.hasRead - Whether or not to immediately mark
|
|
* the message as read.
|
|
* @param {string} messageDetails.message - The received message to display.
|
|
* @param {string} messageDetails.messageType - The kind of message, such as
|
|
* "error" or "local" or "remote".
|
|
* @param {string} messageDetails.timestamp - A timestamp to display for when
|
|
* the message was received.
|
|
* @param {string} messageDetails.isReaction - Whether or not the
|
|
* message is a reaction message.
|
|
* @returns {{
|
|
* type: ADD_MESSAGE,
|
|
* displayName: string,
|
|
* hasRead: boolean,
|
|
* message: string,
|
|
* messageType: string,
|
|
* timestamp: string,
|
|
* isReaction: boolean
|
|
* }}
|
|
*/
|
|
export function addMessage(messageDetails: Object) {
|
|
return {
|
|
type: ADD_MESSAGE,
|
|
...messageDetails
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Adds a reaction to a chat message.
|
|
*
|
|
* @param {Object} reactionDetails - The reaction to add.
|
|
* @param {string} reactionDetails.participantId - The ID of the message to react to.
|
|
* @param {string} reactionDetails.reactionList - The reaction to add.
|
|
* @param {string} reactionDetails.messageId - The receiver ID of the reaction.
|
|
* @returns {{
|
|
* type: ADD_MESSAGE_REACTION,
|
|
* participantId: string,
|
|
* reactionList: string[],
|
|
* messageId: string
|
|
* }}
|
|
*/
|
|
export function addMessageReaction(reactionDetails: Object) {
|
|
return {
|
|
type: ADD_MESSAGE_REACTION,
|
|
...reactionDetails
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Edits an existing chat message.
|
|
*
|
|
* @param {Object} message - The chat message to edit/override. The messages will be matched from the state
|
|
* comparing the messageId.
|
|
* @returns {{
|
|
* type: EDIT_MESSAGE,
|
|
* message: Object
|
|
* }}
|
|
*/
|
|
export function editMessage(message: Object) {
|
|
return {
|
|
type: EDIT_MESSAGE,
|
|
message
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Clears the chat messages in Redux.
|
|
*
|
|
* @returns {{
|
|
* type: CLEAR_MESSAGES
|
|
* }}
|
|
*/
|
|
export function clearMessages() {
|
|
return {
|
|
type: CLEAR_MESSAGES
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Action to signal the closing of the chat dialog.
|
|
*
|
|
* @returns {{
|
|
* type: CLOSE_CHAT
|
|
* }}
|
|
*/
|
|
export function closeChat() {
|
|
return {
|
|
type: CLOSE_CHAT
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Sends a chat message to everyone in the conference.
|
|
*
|
|
* @param {string} message - The chat message to send out.
|
|
* @param {boolean} ignorePrivacy - True if the privacy notification should be ignored.
|
|
* @returns {{
|
|
* type: SEND_MESSAGE,
|
|
* ignorePrivacy: boolean,
|
|
* message: string
|
|
* }}
|
|
*/
|
|
export function sendMessage(message: string, ignorePrivacy = false) {
|
|
return {
|
|
type: SEND_MESSAGE,
|
|
ignorePrivacy,
|
|
message
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Sends a reaction to a message.
|
|
*
|
|
* @param {string} reaction - The reaction to send.
|
|
* @param {string} messageId - The message ID to react to.
|
|
* @param {string} receiverId - The receiver ID of the reaction.
|
|
* @returns {Function}
|
|
*/
|
|
export function sendReaction(reaction: string, messageId: string, receiverId?: string) {
|
|
|
|
return {
|
|
type: SEND_REACTION,
|
|
reaction,
|
|
messageId,
|
|
receiverId
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initiates the sending of a private message to the supplied participant.
|
|
*
|
|
* @param {IParticipant} participant - The participant to set the recipient to.
|
|
* @returns {{
|
|
* participant: IParticipant,
|
|
* type: SET_PRIVATE_MESSAGE_RECIPIENT
|
|
* }}
|
|
*/
|
|
export function setPrivateMessageRecipient(participant?: Object) {
|
|
return {
|
|
participant,
|
|
type: SET_PRIVATE_MESSAGE_RECIPIENT
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initiates the sending of a private message to the supplied participantId.
|
|
*
|
|
* @param {string} participantId - The participant id to set the recipient to.
|
|
* @returns {{
|
|
* participant: IParticipant,
|
|
* type: SET_PRIVATE_MESSAGE_RECIPIENT
|
|
* }}
|
|
*/
|
|
export function setPrivateMessageRecipientById(participantId: string) {
|
|
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
|
const participant = getParticipantById(getState(), participantId);
|
|
|
|
if (participant) {
|
|
dispatch(setPrivateMessageRecipient(participant));
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Set the value of the currently focused tab.
|
|
*
|
|
* @param {string} tabId - The id of the currently focused tab.
|
|
* @returns {{
|
|
* type: SET_FOCUSED_TAB,
|
|
* tabId: string
|
|
* }}
|
|
*/
|
|
export function setFocusedTab(tabId: ChatTabs) {
|
|
return {
|
|
type: SET_FOCUSED_TAB,
|
|
tabId
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Opens the chat panel with CC tab active.
|
|
*
|
|
* @returns {Object} The redux action.
|
|
*/
|
|
export function openCCPanel() {
|
|
return async (dispatch: IStore['dispatch']) => {
|
|
dispatch(setFocusedTab(ChatTabs.CLOSED_CAPTIONS));
|
|
dispatch({
|
|
type: OPEN_CHAT
|
|
});
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
* Initiates the sending of messages between a moderator and a lobby attendee.
|
|
*
|
|
* @param {Object} lobbyChatInitializedInfo - The information about the attendee and the moderator
|
|
* that is going to chat.
|
|
*
|
|
* @returns {Function}
|
|
*/
|
|
export function onLobbyChatInitialized(lobbyChatInitializedInfo: { attendee: IParticipant; moderator: IParticipant; }) {
|
|
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
|
const state = getState();
|
|
const conference = getCurrentConference(state);
|
|
|
|
const lobbyLocalId = conference?.myLobbyUserId();
|
|
|
|
if (!lobbyLocalId) {
|
|
return;
|
|
}
|
|
|
|
if (lobbyChatInitializedInfo.moderator.id === lobbyLocalId) {
|
|
dispatch({
|
|
type: SET_LOBBY_CHAT_RECIPIENT,
|
|
participant: lobbyChatInitializedInfo.attendee,
|
|
open: true
|
|
});
|
|
}
|
|
|
|
if (lobbyChatInitializedInfo.attendee.id === lobbyLocalId) {
|
|
return dispatch({
|
|
type: SET_LOBBY_CHAT_RECIPIENT,
|
|
participant: lobbyChatInitializedInfo.moderator,
|
|
open: false
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Sets the lobby room's chat active state.
|
|
*
|
|
* @param {boolean} value - The active state.
|
|
*
|
|
* @returns {Object}
|
|
*/
|
|
export function setLobbyChatActiveState(value: boolean) {
|
|
return {
|
|
type: SET_LOBBY_CHAT_ACTIVE_STATE,
|
|
payload: value
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Notifies the private chat recipients list changed.
|
|
*
|
|
* @returns {Object}
|
|
*/
|
|
export function notifyPrivateRecipientsChanged() {
|
|
return (dispatch: IStore['dispatch']) => {
|
|
const timestamp = Date.now();
|
|
|
|
return dispatch({
|
|
type: NOTIFY_PRIVATE_RECIPIENTS_CHANGED,
|
|
payload: timestamp
|
|
});
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Removes lobby type messages.
|
|
*
|
|
* @param {boolean} removeLobbyChatMessages - Should remove messages from chat (works only for accepted users).
|
|
* If not specified, it will delete all lobby messages.
|
|
*
|
|
* @returns {Object}
|
|
*/
|
|
export function removeLobbyChatParticipant(removeLobbyChatMessages?: boolean) {
|
|
return {
|
|
type: REMOVE_LOBBY_CHAT_PARTICIPANT,
|
|
removeLobbyChatMessages
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Handles initial setup of lobby message between
|
|
* Moderator and participant.
|
|
*
|
|
* @param {string} participantId - The participant id.
|
|
*
|
|
* @returns {Object}
|
|
*/
|
|
export function handleLobbyChatInitialized(participantId: string) {
|
|
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
|
if (!participantId) {
|
|
return;
|
|
}
|
|
const state = getState();
|
|
const conference = state['features/base/conference'].conference;
|
|
const { knockingParticipants } = state['features/lobby'];
|
|
const { lobbyMessageRecipient } = state['features/chat'];
|
|
const me = getLocalParticipant(state);
|
|
const lobbyLocalId = conference?.myLobbyUserId();
|
|
|
|
|
|
if (lobbyMessageRecipient && lobbyMessageRecipient.id === participantId) {
|
|
return dispatch(setLobbyChatActiveState(true));
|
|
}
|
|
|
|
const attendee = knockingParticipants.find(p => p.id === participantId);
|
|
|
|
if (attendee && attendee.chattingWithModerator === lobbyLocalId) {
|
|
return dispatch({
|
|
type: SET_LOBBY_CHAT_RECIPIENT,
|
|
participant: attendee,
|
|
open: true
|
|
});
|
|
}
|
|
|
|
if (!attendee) {
|
|
return;
|
|
}
|
|
|
|
const payload = { type: LOBBY_CHAT_INITIALIZED,
|
|
moderator: {
|
|
...me,
|
|
name: 'Moderator',
|
|
id: lobbyLocalId
|
|
},
|
|
attendee };
|
|
|
|
// notify attendee privately.
|
|
conference?.sendLobbyMessage(payload, attendee.id);
|
|
|
|
// notify other moderators.
|
|
return conference?.sendLobbyMessage(payload);
|
|
};
|
|
}
|