react-native-chating-ui-kit
Version:
CometChat React Native UI Kit is a collection of custom UI Components designed to build text , chat and calling features in your application. The UI Kit is developed to keep developers in mind and aims to reduce development efforts significantly
250 lines • 11.6 kB
JavaScript
import { CometChat } from '@cometchat-pro/react-native-chat';
import React, { useContext, useEffect, useRef, useState } from 'react';
import { FlatList, Image, Text, TouchableOpacity, View } from 'react-native';
import { CometChatContext, CometChatDate, CometChatListItem, localize } from '../../shared';
import { CallHistoryStyle } from './CallHistoryStyle';
import { CometChatUIEventHandler } from '../../shared/events/CometChatUIEventHandler/CometChatUIEventHandler';
import { AudioCallIcon, VideoCallIcon, LoadingIcon, DetailIcon, BackIcon, CheckIcon, SelectionIcon } from "./resources";
import { CallContstatnts } from '../../shared/constants/UIKitConstants';
import { Style } from './style';
import { messageStatus } from '../../shared/utils/CometChatMessageHelper';
import { MessageCategoryConstants } from '../../shared/constants/UIKitConstants';
import { MessageTypeConstants } from '../../shared/constants/UIKitConstants';
const callListenerId = "uiEvents_" + new Date().getTime();
const CometChatCallHistory = (props) => {
const { title = localize("CALL_HISTORY"), SubtitleView, ListItemView, AppBarOptions, options, messageRequestBuilder, hideSeperator = false, BackButton, showBackButton = true, selectionMode = "multiple", onSelection, EmptyStateView, emptyStateText, ErrorStateView, errorStateText, loadingIcon, LoadingStateView, hideError, onItemPress, onItemLongPress, onInfoIconPress, infoIcon, onError, onBack, avatarStyle, statusIndicatorStyle, listItemStyle, callHistoryStyle, headViewContainerStyle, bodyViewContainerStyle, tailViewContainerStyle, } = props;
const { theme } = useContext(CometChatContext);
const _style = new CallHistoryStyle({
titleFont: theme.typography.heading,
titleColor: theme.palette.getAccent(),
backgroundColor: theme.palette.getBackgroundColor(),
...callHistoryStyle
});
const { backgroundColor, height, width, border, borderRadius, titleColor, titleFont, loadingTint, } = _style;
const [list, setList] = useState([]);
const [listState, setListState] = useState("loading");
const [selecting, setSelecting] = useState(false);
const [selectedItems, setSelectedItems] = useState({});
const loggedInUser = useRef(null);
const callRequestBuilderRef = useRef((messageRequestBuilder && messageRequestBuilder.build()) ?? new CometChat.MessagesRequestBuilder()
.setCategories([MessageCategoryConstants.call, MessageCategoryConstants.custom])
.setTypes([MessageTypeConstants.audio, MessageTypeConstants.video, MessageTypeConstants.meeting])
.setLimit(30)
.build());
const fetchCallHistory = () => {
setListState("loading");
callRequestBuilderRef.current.fetchPrevious()
.then(callLogs => {
console.log(callLogs.length);
setList([...list, ...callLogs.reverse()]);
setListState("done");
})
.catch(err => {
onError && onError(err);
setListState("error");
});
};
useEffect(() => {
CometChat.getLoggedinUser()
.then(u => {
loggedInUser.current = u;
fetchCallHistory();
})
.catch(e => {
onError(e);
});
CometChat.addCallListener(callListenerId, new CometChat.CallListener({
onIncomingCallReceived: (call) => {
addNewCall(call);
},
onOutgoingCallAccepted: (call) => {
addNewCall(call);
},
onOutgoingCallRejected: (call) => {
addNewCall(call);
},
onIncomingCallCancelled: (call) => {
addNewCall(call);
}
}));
CometChatUIEventHandler.addMessageListener(callListenerId, {
ccMessageSent: ({ message, status }) => {
status == messageStatus.success && addNewCall(message);
}
});
CometChatUIEventHandler.addCallListener(callListenerId, {
ccOutgoingCall: ({ call }) => { addNewCall(call); },
ccCallAccepted: ({ call }) => { addNewCall(call); },
ccCallRejected: ({ call }) => { addNewCall(call); },
ccCallEnded: ({ call }) => { addNewCall(call); }
});
return () => {
CometChat.removeCallListener(callListenerId);
CometChatUIEventHandler.removeMessageListener(callListenerId);
};
}, []);
const addNewCall = (call) => {
setList([call, ...list]);
};
const DefaultSubtitleView = ({ call }) => {
if (SubtitleView)
return SubtitleView(call);
return (<View style={[Style.row]}>
<Image source={call['type'] == CallContstatnts.audioCall ? AudioCallIcon : VideoCallIcon} style={{ height: 16, width: 16, alignSelf: "center", tintColor: theme.palette.getAccent700() }}/>
<Text style={{ color: theme.palette.getAccent(), marginStart: 8 }}>
{call['type'] == "meeting" ?
"conference call" :
call['status']}
</Text>
</View>);
};
const TailView = ({ call }) => {
return (<View style={[Style.row, { alignItems: "center" }]}>
<CometChatDate timeStamp={call['updatedAt'] * 1000} pattern={'dayDateFormat'} style={{ textColor: theme.palette.getAccent() }}/>
<TouchableOpacity onPress={() => onInfoIconPress && onInfoIconPress({ call })} style={{ marginStart: 8 }}>
<Image source={infoIcon || DetailIcon} style={{ height: 24, width: 24, tintColor: theme.palette.getPrimary() }}/>
</TouchableOpacity>
</View>);
};
//returns index from selected items
const isSelected = (item) => {
return Object.keys(selectedItems).includes(item.id);
};
const longPress = (item) => {
if (onItemLongPress) {
onItemLongPress(item);
return;
}
setSelecting(true);
if (selectionMode == "none")
return;
if (selectionMode == "single")
setSelectedItems({ [item['id']]: item });
else {
// let index = isSelected(item);
if (isSelected(item)) {
let tmp = { ...selectedItems };
delete tmp[item.id];
setSelectedItems({ [tmp['id']]: tmp });
}
else {
setSelectedItems({
...selectedItems,
[item['id']]: item
});
}
}
};
const onPress = (item) => {
if (!selecting) {
onItemPress && onItemPress(item);
return;
}
//add to selected
switch (selectionMode) {
case "single":
setSelectedItems({ [item['id']]: item });
break;
case "multiple":
if (isSelected(item)) {
let tmp = { ...selectedItems };
delete tmp[item.id];
setSelectedItems(tmp);
}
else {
setSelectedItems({
...selectedItems,
[item['id']]: item
});
}
break;
}
};
const getCallDetails = (call) => {
const { category, type, callInitiator, callReceiver, receiverId, receiver } = call;
if (category == "custom" && type == "meeting") {
return {
title: receiver['name'],
avatarUrl: receiver['icon']
};
}
else if (category == "call") {
return {
title: loggedInUser.current['uid'] == receiverId ? callInitiator['name'] : callReceiver['name'],
avatarUrl: loggedInUser.current['uid'] == receiverId ? callInitiator['avatar'] : callReceiver['avatar'],
};
}
return { title: "", avatarUrl: undefined };
};
const _render = ({ item, index }) => {
if (ListItemView)
return <ListItemView call={item}/>;
const { title, avatarUrl } = getCallDetails(item);
return <CometChatListItem id={item.id} avatarName={title} title={title} listItemStyle={listItemStyle ? listItemStyle : { height: 70 }} headViewContainerStyle={headViewContainerStyle
? headViewContainerStyle
: { marginHorizontal: 9 }} bodyViewContainerStyle={bodyViewContainerStyle ? bodyViewContainerStyle : {}} tailViewContainerStyle={tailViewContainerStyle ? tailViewContainerStyle : {}} avatarURL={avatarUrl} statusIndicatorIcon={selectedItems[item.id] && CheckIcon} SubtitleView={() => SubtitleView ? <SubtitleView {...item}/> : <DefaultSubtitleView call={item}/>} TailView={TailView ? () => <TailView call={item}/> : null} statusIndicatorStyle={selectedItems[item.id]
? {
...statusIndicatorStyle,
borderRadius: 10,
height: 20,
width: 20,
}
: statusIndicatorStyle} avatarStyle={avatarStyle} options={() => options && options(item)} onPress={() => onPress(item)} onLongPress={() => longPress(item)} hideSeparator={hideSeperator}/>;
};
const EmptyView = () => {
if (EmptyStateView)
return <EmptyStateView />;
return (<View style={[Style.container]}>
<Text>{emptyStateText || localize("NO_CALL_HISTORY")}</Text>
</View>);
};
const ErrorView = () => {
if (hideError)
return null;
if (ErrorStateView)
return <ErrorStateView />;
return <View style={[Style.container]}>
<Text>{errorStateText || localize("SOMETHING_WRONG")}</Text>
</View>;
};
const LoadingView = () => {
if (LoadingStateView)
return <LoadingStateView />;
return <View style={[Style.container]}>
<Image source={loadingIcon || LoadingIcon} style={[Style.imageStyle, { tintColor: "black" || loadingTint }]}/>
</View>;
};
const selection = () => {
if (onSelection)
onSelection(Object.values(selectedItems));
setSelecting(false);
setSelectedItems({});
};
return (<View style={{ backgroundColor, height, width, borderRadius, ...border }}>
<View style={[Style.row, Style.headerStyle, { height: 60 }]}>
<View style={Style.row}>
{showBackButton ?
BackButton ??
<TouchableOpacity style={Style.imageStyle} onPress={onBack}>
<Image source={BackIcon} style={[Style.imageStyle, { tintColor: theme.palette.getPrimary() }]}/>
</TouchableOpacity> : null}
<Text style={[{ color: titleColor, ...titleFont }]}>{title}</Text>
</View>
<View style={Style.row}>
{AppBarOptions && <AppBarOptions />}
{selecting ?
<TouchableOpacity onPress={selection}>
<Image source={SelectionIcon} resizeMode='contain' style={[Style.imageStyle, { tintColor: theme.palette.getPrimary() }]}/>
</TouchableOpacity> : null}
</View>
</View>
{listState == "loading" && list.length == 0 ?
<LoadingView /> :
listState == "error" && list.length == 0 ?
<ErrorView /> :
list.length == 0 ?
<EmptyView /> :
<FlatList data={list} keyExtractor={(item) => item.id} renderItem={_render} onEndReached={fetchCallHistory}/>}
</View>);
};
//# sourceMappingURL=CometChatCallHistory.js.map