客服,即時(shí)通訊功能實(shí)現(xiàn)
實(shí)現(xiàn)方式:
早期使用的是每個(gè)用戶有聊天室和消息,監(jiān)聽(tīng)新的聊天室的創(chuàng)建和新消息的創(chuàng)建,經(jīng)過(guò)一段時(shí)間功能增加發(fā)現(xiàn)這種方式很費(fèi)力并不好,
更好的實(shí)現(xiàn)是每個(gè)用戶相當(dāng)于有一個(gè)收件箱,只要全局監(jiān)聽(tīng)用戶的收件箱就可使輕松實(shí)現(xiàn),監(jiān)聽(tīng)聊天室和新消息創(chuàng)建難以實(shí)現(xiàn)的功能。
package:"apollo-link": "^1.2.14","apollo-link-http": "^1.5.17","aws-amplify": "^3.3.1","aws-amplify-react-native": "^4.2.6","aws-appsync": "^4.0.1","aws-appsync-auth-link": "^2.0.3","redux": "^4.0.5",
需要監(jiān)聽(tīng):用戶的收件箱,和消息的改變(消息已讀未讀,撤回等)
思路:
用戶的所有消息,所有聊天室放在redux中管理,
新消息彈窗提醒
當(dāng)有新消息發(fā)來(lái),新的消息帶有所屬聊天室的id,消息的內(nèi)容,發(fā)送接收方的id,是否已讀等字段。當(dāng)用戶的收件箱收到新消息可頂部彈窗提醒,彈窗根據(jù)聊天室的id可跳轉(zhuǎn)到聊天室頁(yè)面中,
每執(zhí)行上述操作時(shí),判斷當(dāng)前app是否處于后臺(tái),若處于后臺(tái)模式則調(diào)用sdk,手機(jī)發(fā)送一條消息提醒a(bǔ)pp來(lái)新消息了。
每條消息的發(fā)送,用戶點(diǎn)擊發(fā)送消息時(shí),可先將信息插入到redux中,同時(shí)發(fā)送請(qǐng)求真正發(fā)送消息,此期間可有信息發(fā)送中加載動(dòng)畫(huà)
接收消息
每當(dāng)接收到新消息,要判斷用戶當(dāng)前是否在聊天室內(nèi),又是否是正在聊天的聊天室發(fā)送的新消息,如果是則不用頂部彈窗提醒,將新消息插入到redux中,實(shí)現(xiàn)新消息的接收,若用戶不在聊天室,或者不在新消息所屬的聊天室則彈窗新消息提醒,
已讀/未讀消息
每條消息都在有hasRead字段表示這條消息對(duì)方是否已讀,默認(rèn)都是false,讓用戶進(jìn)入聊天室時(shí),獲取當(dāng)前聊天室的消息中是對(duì)方發(fā)送的同時(shí)hasRead為false的消息,發(fā)送請(qǐng)求更改這條消息的hasRead字段為true,可想將redux中的數(shù)據(jù)是想更改,同時(shí)發(fā)送請(qǐng)求去更改數(shù)據(jù)庫(kù)中的消息信息,提升用戶體驗(yàn)
當(dāng)用戶發(fā)送更改消息的請(qǐng)求后,對(duì)方會(huì)監(jiān)聽(tīng)到這條消息被更改,不需要重新獲取消息,只需要根據(jù)這條消息的id去更改redux中的數(shù)據(jù)即可
未讀消息數(shù)量
同樣放在redux中管理,進(jìn)入app時(shí),獲取全部收件箱中的信息,判斷hasRead為false并且發(fā)送者id是自己時(shí)數(shù)量加1,拿到當(dāng)前未讀消息總數(shù),當(dāng)有新的消息到來(lái)時(shí)發(fā)送dispatch將未讀總數(shù)加1,當(dāng)用戶進(jìn)入聊天室讀取消息時(shí),在上面設(shè)置已讀消息時(shí)可拿到已讀幾條消息,已讀幾條全部消息數(shù)量就減幾,即可實(shí)現(xiàn)未讀消息數(shù)量,
消息列表
每條消息列表上消息這個(gè)聊天室中又幾條未讀消息,以及最近一條消息的內(nèi)容,以及,如果你是店家,顯示買(mǎi)家的頭像和昵稱(chēng),如果你是買(mǎi)家顯示商店的logo和名稱(chēng),需要做個(gè)判斷(聊天室數(shù)據(jù)中有聊天室中商店的信息和兩方的id),商家端判斷聊天室中的商店的所有者是不是自己,需要拿到聊天室的userIds即用戶id組成的數(shù)組中和自己id不同的即是買(mǎi)家id,獲取買(mǎi)家的公開(kāi)信息,以顯示
消息列表中每條聊天室展示獲取未讀消息:去redux中根據(jù)聊天室id獲取這個(gè)聊天室中的信息中發(fā)送者id和自己id不同并且hasRead為false的消息數(shù)量
最新消息:同樣通過(guò)聊天室id拿到消息,拿最后一項(xiàng)顯示
以上實(shí)現(xiàn)就需要redux中的數(shù)據(jù)保存形式是一個(gè)對(duì)象,鍵是聊天室的id,值是聊天室中的消息數(shù)組
實(shí)現(xiàn)監(jiān)聽(tīng)代碼示例:
消息創(chuàng)建的訂閱
export const createdMessageInbox = /* GraphQL */ `
subscription CreatedMessageInbox($receiverId: ID!) {
createdMessageInbox(receiverId: $receiverId) {
id
content
senderId
receiverId
conversationId
sentTime
hasRead
}
}
`;let subCreatedMessage: any = null; // 外面定義監(jiān)聽(tīng)以實(shí)現(xiàn)取消訂閱
const subscribeCreatedMessageInbox = () => {
subCreatedMessage?.unsubscribe(); // Subscription before unsubscribe
subCreatedMessage = API.graphql(
graphqlOperation(createdMessageInbox, { receiverId: username })
).subscribe({
next: (event: any) => {
if (event?.value?.data) { // 如果正常有數(shù)據(jù)的話
const message = event.value.data.createdMessageInbox; // 新消息
const conversationId = message.conversationId; // 新消息所屬聊天室的id
// Send a system notification when the application is in the background
if (AppState.currentState !== "active") {
sendPushNotification({
title: "new message",
body: message.content,
});
}
// Add to Redux to save
receiverMessageInbox({ // redux將新消息放到消息數(shù)組中
message,
conversationId,
})(dispatch);
// New news pop-up
haveNewMessage()(dispatch);// 新消息彈窗信息組件獲取當(dāng)前狀態(tài),判斷是否需要彈出
popupParams({ // 新消息彈窗所需的信息
message: message.content,
conversationId,
receiverId: message.senderId, // Senderid is username not receiverId
})(dispatch);
unreadMessageInboxNumber(1)(dispatch); // add 1 unread messageInbox quantity
}
},
error: (err: any) => {
error("createdMessage error", err);
},
});
};具體代碼為詳細(xì)展示,以上僅是實(shí)現(xiàn)思路。
最后如果對(duì)你有幫助,或疑問(wèn)歡迎點(diǎn)贊評(píng)論,一鍵三連~
