@cometchat/chat-uikit-react-native
Version:
Ready-to-use Chat UI Components for React Native
301 lines • 14.1 kB
JavaScript
import { CometChat } from "@cometchat/chat-sdk-react-native";
import React from "react";
import { Modal, View } from "react-native";
import { ChatConfigurator, CometChatUIEventHandler, CometChatUIKit } from "../shared";
import { CallContstatnts, MessageCategoryConstants, MessageTypeConstants, } from "../shared/constants/UIKitConstants";
import { DataSourceDecorator } from "../shared/framework/DataSourceDecorator";
import { CometChatMessageTemplate } from "../shared/modals";
import { localize } from "../shared/resources/CometChatLocalize";
import { permissionUtil } from "../shared/utils/PermissionUtil";
import { CallUIEvents } from "./CallEvents";
import { CallingPackage } from "./CallingPackage";
import { CallUtils } from "./CallUtils";
import { CometChatMeetCallBubble } from "./CometChatCallBubble";
import { CometChatCallButtons } from "./CometChatCallButtons";
import { CometChatOngoingCall } from "./CometChatOngoingCall";
import { DateHelper, dateHelperInstance } from "../shared/helper/dateHelper";
import { Icon } from "../shared/icons/Icon";
import { CometChatCallActionBubble } from "./CometChatCallBubble/CometChatCallBubble";
const CometChatCalls = CallingPackage.CometChatCalls;
/**
* CallingExtensionDecorator extends the DataSourceDecorator to add calling-specific
* configurations and templates.
*
* @class CallingExtensionDecorator
* @extends {DataSourceDecorator}
*/
export class CallingExtensionDecorator extends DataSourceDecorator {
/**
* Optional calling configuration.
*/
configuration;
/**
* The logged in CometChat user.
*/
loggedInUser;
/**
* Creates an instance of CallingExtensionDecorator.
*
* @param {object} props - The properties object.
* @param {DataSource} props.dataSource - The original data source.
* @param {CallingConfiguration} [props.configuration] - Optional calling configuration.
*/
constructor(props) {
super(props.dataSource);
CometChat.getLoggedinUser()
.then((user) => {
this.loggedInUser = user;
})
.catch((err) => {
console.log("unable to get logged in user.");
});
if (props.configuration) {
this.configuration = props.configuration;
}
}
/**
* Returns a unique identifier for this decorator.
*
* @returns {string} The identifier.
*/
getId() {
return "call";
}
/**
* Determines whether a message is deleted.
*
* @param {CometChat.BaseMessage} message - The message to check.
* @returns {boolean} True if the message is deleted; otherwise false.
*/
isDeletedMessage(message) {
return message.getDeletedBy() != null;
}
/**
* Retrieves all supported message types including call types.
*
* @returns An array of message type strings.
*/
getAllMessageTypes() {
let types = super.getAllMessageTypes();
types.push(CallContstatnts.audioCall);
types.push(CallContstatnts.videoCall);
types.push(MessageTypeConstants.meeting);
return types;
}
/**
* Retrieves all supported message categories including call-related categories.
*
* @returns An array of message category strings.
*/
getAllMessageCategories() {
let categories = super.getAllMessageCategories();
categories.push(MessageCategoryConstants.call);
categories.push(MessageCategoryConstants.custom);
return categories;
}
/**
* Renders the call bubble view for one-to-one call messages.
*
* @param {object} param0 - The props object.
* @param {any} param0.message - The call message.
* @param {CometChatTheme} param0.theme - The theme.
* @returns {JSX.Element|null} The rendered call bubble view.
*/
UserCallBubbleView = ({ message, theme }) => {
if (this.isDeletedMessage(message))
return null;
const callStatus = CallUtils.getCallStatus(message, this.loggedInUser);
return (<CometChatCallActionBubble titleText={callStatus.callMessageText} style={theme?.messageListStyles.callActionBubbleStyles} icon={<Icon name={callStatus.selectedIcon} height={callStatus.callMessageText === localize("MISSED_CALL")
? theme.messageListStyles?.callActionBubbleStyles?.missedCallIconStyle?.height ?? 16
: theme.messageListStyles?.callActionBubbleStyles?.iconStyle?.height ?? 16} width={callStatus.callMessageText === localize("MISSED_CALL")
? theme.messageListStyles?.callActionBubbleStyles?.missedCallIconStyle?.width ?? 16
: theme.messageListStyles?.callActionBubbleStyles?.iconStyle?.width ?? 16} color={callStatus.callMessageText === localize("MISSED_CALL")
? theme.messageListStyles?.callActionBubbleStyles?.missedCallIconStyle?.tintColor
: theme.messageListStyles?.callActionBubbleStyles?.iconStyle?.tintColor} imageStyle={callStatus.callMessageText === localize("MISSED_CALL")
? theme.messageListStyles?.callActionBubbleStyles?.missedCallIconStyle
: theme.messageListStyles?.callActionBubbleStyles?.iconStyle} containerStyle={callStatus.callMessageText === localize("MISSED_CALL")
? theme.messageListStyles?.callActionBubbleStyles?.missedCallIconContainerStyle
: theme.messageListStyles?.callActionBubbleStyles?.iconContainerStyle}/>}/>);
};
/**
* Returns the audio call message template for one-to-one chats.
*
* @param {CometChatTheme} theme - The theme to use for the template.
* @returns {CometChatMessageTemplate} The audio call message template.
*/
getUserAudioCallTemplate = (theme) => {
return new CometChatMessageTemplate({
category: MessageCategoryConstants.call,
type: MessageTypeConstants.audio,
BubbleView: (message) => {
return this.UserCallBubbleView({
message,
theme,
});
},
});
};
/**
* Returns the video call message template for one-to-one chats.
*
* @param {CometChatTheme} theme - The theme to use for the template.
* @returns {CometChatMessageTemplate} The video call message template.
*/
getUserVideoCallTemplates = (theme) => {
return new CometChatMessageTemplate({
category: MessageCategoryConstants.call,
type: MessageTypeConstants.video,
BubbleView: (message) => {
return this.UserCallBubbleView({
message,
theme,
});
},
});
};
/**
* Renders the group call bubble view.
*
* @param {object} props - The props for the group call bubble view.
* @param {CometChat.CustomMessage} props.message - The call message.
* @param {CometChatTheme} props.theme - The theme.
* @param {string} props.alignment - Alignment for the bubble.
* @returns {JSX.Element} The rendered group call bubble view.
*/
GroupCallBubbleView = (props) => {
let loggedInUser = CometChatUIKit.loggedInUser;
const { message, theme, alignment } = props;
if (this.isDeletedMessage(message))
return ChatConfigurator.dataSource.getDeleteMessageBubble(message, theme);
const isSentByMe = message.getSender().getUid() === loggedInUser.getUid();
const _style = isSentByMe
? theme.messageListStyles.outgoingMessageBubbleStyles?.meetCallBubbleStyles
: theme.messageListStyles.incomingMessageBubbleStyles?.meetCallBubbleStyles;
const sentAt = message?.getSentAt() ? message.getSentAt() * 1000 : Date.now();
const callType = message.getCustomData().callType;
const BubbleIcon = (() => {
if (isSentByMe) {
if (callType === "audio") {
return <Icon name='outgoing-audio-fill' color={_style?.iconStyle?.tintColor}/>;
}
return <Icon name='outgoing-video-fill' color={_style?.iconStyle?.tintColor}/>;
}
else {
if (callType === "audio") {
return <Icon name='incoming-audio-fill' color={_style?.iconStyle?.tintColor}/>;
}
return <Icon name='incoming-video-fill' color={_style?.iconStyle?.tintColor}/>;
}
})();
return (<View>
<CometChatMeetCallBubble buttonText={localize("JOIN")} titleText={callType === "audio" ? localize("AUDIO_CALL") : localize("VIDEO_CALL")} icon={BubbleIcon} onClick={() => this.startDirectCall(message.getCustomData()["sessionId"], message, theme, callType)} style={_style ?? {}} subTitleText={dateHelperInstance.getFormattedDate(sentAt, DateHelper.patterns.callBubble)}/>
</View>);
};
/**
* Initiates a direct call by checking permissions and showing the ongoing call screen.
*
* @param sessionId - The call session ID.
* @param message - The call message.
* @param [theme] - The theme.
* @param [callType] - The type of call (audio/video).
* @returns
*/
async startDirectCall(sessionId, message, theme, callType) {
if (!(await permissionUtil.startResourceBasedTask(["mic", "camera"]))) {
return;
}
const callSettingsBuilder = (this.configuration?.groupCallSettingsBuilder
? this.configuration?.groupCallSettingsBuilder(undefined, message.getReceiver(), callType === "audio")
: new CometChatCalls.CallSettingsBuilder().setIsAudioOnlyCall(callType === "audio")).setCallEventListener(new CometChatCalls.OngoingCallListener({
onCallEndButtonPressed: () => {
CometChatUIEventHandler.emitCallEvent(CallUIEvents.ccShowOngoingCall, {
child: null,
});
},
onError: (error) => {
CometChatUIEventHandler.emitCallEvent(CallUIEvents.ccShowOngoingCall, {
child: null,
});
},
}));
const ongoingCallScreen = (<Modal>
<CometChatOngoingCall sessionID={sessionId} callSettingsBuilder={callSettingsBuilder} onError={(e) => {
CometChatUIEventHandler.emitCallEvent(CallUIEvents.ccShowOngoingCall, {
child: null,
});
}}/>
</Modal>);
CometChatUIEventHandler.emitCallEvent(CallUIEvents.ccShowOngoingCall, {
child: ongoingCallScreen,
});
}
/**
* Renders the call buttons in the auxiliary header app bar.
*
* @param [user] - The user for one-to-one chats.
* @param [group] - The group for group chats.
* @param [additionalParams] - Additional parameters.
* @returns The rendered call buttons or null if conditions are not met.
*/
getAuxiliaryHeaderAppbarOptions(user, group, additionalAuxiliaryHeaderOptionsParams) {
// For one-to-one chats: if a user exists and is blocked, don't render the call buttons.
if (user && !group && user.getBlockedByMe()) {
return null;
}
return (<View>
<CometChatCallButtons user={user} group={group} {...this.configuration?.callButtonsConfiguration} style={additionalAuxiliaryHeaderOptionsParams?.callButtonStyle} hideVoiceCallButton={additionalAuxiliaryHeaderOptionsParams?.hideVoiceCallButton} hideVideoCallButton={additionalAuxiliaryHeaderOptionsParams?.hideVideoCallButton}/>
</View>);
}
/**
* Returns the group call template to render group call messages.
*
* @param {CometChatTheme} theme - The theme.
* @returns {CometChatMessageTemplate} The group call message template.
*/
getGroupCallTemplate = (theme) => {
return new CometChatMessageTemplate({
category: MessageCategoryConstants.custom,
type: MessageTypeConstants.meeting,
ContentView: (message, alignment) => this.GroupCallBubbleView({ message: message, alignment, theme }),
StatusInfoView: (message, alignment) => {
if (message.getDeletedAt()) {
return null;
}
return <></>;
},
options: (loggedInUser, messageObject, group) => {
return super.getCommonOptions(loggedInUser, messageObject, group);
},
});
};
/**
* Retrieves all message templates including call-related templates.
*
* @param {CometChatTheme} theme - The theme.
* @param {AdditionalParams} [additionalParams] - Additional parameters.
* @returns {CometChatMessageTemplate[]} An array of message templates.
*/
getAllMessageTemplates(theme, additionalParams) {
let templates = super.getAllMessageTemplates(theme, additionalParams);
templates.push(this.getUserAudioCallTemplate(theme), this.getUserVideoCallTemplates(theme), this.getGroupCallTemplate(theme));
return templates;
}
/**
* Retrieves the last conversation message for display in the conversation list.
*
* @param {CometChat.Conversation} conversation - The conversation object.
* @param {CometChatTheme} [theme] - The theme.
* @returns {string | JSX.Element} The last conversation message.
*/
getLastConversationMessage(conversation, theme) {
if (conversation.getLastMessage()["category"] != "call")
return super.getLastConversationMessage(conversation, theme);
let lastMesssageString = "";
if (conversation.getLastMessage()["type"] == "audio")
lastMesssageString = localize("AUDIO_CALL");
if (conversation.getLastMessage()["type"] == "video")
lastMesssageString = localize("VIDEO_CALL");
return lastMesssageString;
}
}
//# sourceMappingURL=CallingExtensionDecorator.js.map