From 63965ffd69d0529672a44d7df65af81c78928ce1 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Fri, 29 Mar 2024 16:46:12 +0800 Subject: [PATCH] rename --- src/actions/ConversationActions.js | 2 +- src/{lib => channel}/realTimeAPI.js | 0 .../msgUtils.js => channel/whatsappUtils.js} | 0 src/lib/websocketLib2.js | 67 ---- src/stores/ConversationStore.js | 6 +- .../Conversations/ConversationContext_bak.js | 334 ------------------ .../Components/Input/MediaUpload.jsx | 2 +- .../Components/Input/Template.jsx | 2 +- .../Components/InputComposer.jsx | 2 +- 9 files changed, 7 insertions(+), 408 deletions(-) rename src/{lib => channel}/realTimeAPI.js (100%) rename src/{lib/msgUtils.js => channel/whatsappUtils.js} (100%) delete mode 100644 src/lib/websocketLib2.js delete mode 100644 src/stores/Conversations/ConversationContext_bak.js diff --git a/src/actions/ConversationActions.js b/src/actions/ConversationActions.js index fdc327b..6f4947d 100644 --- a/src/actions/ConversationActions.js +++ b/src/actions/ConversationActions.js @@ -1,7 +1,7 @@ import { groupBy, pick, sortArrayByOrder } from '@/utils/utils'; import { fetchJSON, postJSON } from '@/utils/request' -import { parseRenderMessageList } from '@/lib/msgUtils'; +import { parseRenderMessageList } from '@/channel/whatsappUtils'; import { API_HOST } from '@/config'; import { isEmpty } from '@/utils/commons'; import dayjs from 'dayjs'; diff --git a/src/lib/realTimeAPI.js b/src/channel/realTimeAPI.js similarity index 100% rename from src/lib/realTimeAPI.js rename to src/channel/realTimeAPI.js diff --git a/src/lib/msgUtils.js b/src/channel/whatsappUtils.js similarity index 100% rename from src/lib/msgUtils.js rename to src/channel/whatsappUtils.js diff --git a/src/lib/websocketLib2.js b/src/lib/websocketLib2.js deleted file mode 100644 index 7f1db5b..0000000 --- a/src/lib/websocketLib2.js +++ /dev/null @@ -1,67 +0,0 @@ -// websocketLib.js -import { WebSocketSubject } from 'rxjs/webSocket'; -import { retryWhen, delay, take, catchError } from 'rxjs/operators'; - -class WebSocketLib { - constructor(url, authToken, protocol) { - this.url = url; - this.authToken = authToken; - this.protocol = protocol; - } - - connect() { - this.socket$ = new WebSocketSubject({ - url: this.url, - protocol: this.protocol, // Use protocol for message type - openObserver: { - next: () => { - console.log('Connection established'); - // Send authentication message as soon as connection is established - this.socket$.next({ event: 'authenticate', token: this.authToken }); - }, - }, - closeObserver: { - next: () => { - console.log('Connection closed'); - }, - }, - }); - - this.socket$ - .pipe( - retryWhen(errors => - errors.pipe( - delay(1000), // Retry connection every 1 second - take(10), // Maximum of 10 retries - catchError(error => new Error(`Failed to reconnect: ${error}`)) // Throw error after 10 failed retries - ) - ) - ) - .subscribe( - msg => console.log('Received message:', msg), - err => console.error('Received error:', err), - () => console.log('Connection closed') - ); - } - - sendMessage(message) { - if (!this.socket$) { - console.error('Must connect to WebSocket server before sending a message'); - return; - } - - this.socket$.next({ type: 'message', content: message }); - } - - disconnect() { - if (!this.socket$) { - console.error('Must connect to WebSocket server before disconnecting'); - return; - } - - this.socket$.complete(); - this.socket$ = null; - } -} - -export default WebSocketLib; diff --git a/src/stores/ConversationStore.js b/src/stores/ConversationStore.js index e3f24a1..74f0758 100644 --- a/src/stores/ConversationStore.js +++ b/src/stores/ConversationStore.js @@ -1,7 +1,7 @@ import { create } from 'zustand'; -import { RealTimeAPI } from '@/lib/realTimeAPI'; +import { RealTimeAPI } from '@/channel/realTimeAPI'; import { olog, isEmpty } from '@/utils/utils'; -import { receivedMsgTypeMapped, handleNotification } from '@/lib/msgUtils'; +import { receivedMsgTypeMapped, handleNotification } from '@/channel/whatsappUtils'; import { fetchConversationsList, fetchTemplates, fetchMessages } from '@/actions/ConversationActions'; import { devtools } from 'zustand/middleware'; import { WS_URL } from '@/config'; @@ -89,7 +89,7 @@ const websocketSlice = (set, get) => ({ realtimeAPI.onMessage(handleMessage); realtimeAPI.onCompletion(() => addError('Connection broken')); - olog('Connecting to websocket...', realtimeAPI); + olog('Connecting to websocket...'); setWebsocket(realtimeAPI); }, disconnectWebsocket: () => { diff --git a/src/stores/Conversations/ConversationContext_bak.js b/src/stores/Conversations/ConversationContext_bak.js deleted file mode 100644 index ef84d54..0000000 --- a/src/stores/Conversations/ConversationContext_bak.js +++ /dev/null @@ -1,334 +0,0 @@ -import { createContext, useContext, useState, useEffect, useRef } from 'react'; -import { receivedMsgTypeMapped, sentMsgTypeMapped } from '@/lib/msgUtils'; -import { groupBy, isEmpty, pick } from '@/utils/utils'; -import { v4 as uuid } from 'uuid'; - -export const ConversationContext = createContext(); -export const useConversationContext = () => useContext(ConversationContext); -export async function fetchJSON(url, data) { - let params = ''; - let ifp = ''; - if (data) { - params = new URLSearchParams(data).toString(); - ifp = params ? '?' : ifp; - } - ifp = url.includes('?') ? '' : ifp; - const host = /^https?:\/\//i.test(url) ? '' : ''; // HT_HOST; - const response = await fetch(`${host}${url}${ifp}${params}`); - return await response.json(); -} -export async function postJSON(url, obj) { - try { - const response = await fetch(url, { - method: 'POST', - body: JSON.stringify(obj), - headers: { - 'Content-Type': 'application/json', - }, - }); - if (!response.ok) { - throw new Error('Network response was not ok'); - } - return await response.json(); - } catch (error) { - console.error('fetch error:', error); - throw error; - } -} -// const API_HOST = 'http://202.103.68.144:8888'; -const API_HOST = 'https://p9axztuwd7x8a7.mycht.cn/whatsapp_server'; - -export const useConversations = ({loginUser, realtimeAPI}) => { - const { userId } = loginUser; - - const [errors, setErrors] = useState([]); - const [messages, setMessages] = useState([]); // active conversation - const [activeConversations, setActiveConversations] = useState({}); // all active conversation - const [currentID, setCurrentID] = useState(); - const [conversationsList, setConversationsList] = useState([]); // open conversations - const [currentConversation, setCurrentConversation] = useState({ sn: '', customer_name: '', coli_sn: '' }); - const currentConversationRef = useRef(currentConversation); - useEffect(() => { - currentConversationRef.current = currentConversation; - }, [currentConversation]); - - useEffect(() => { - console.log(errors, 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - return () => {}; - }, [errors]) - - useEffect(() => { - realtimeAPI.onError(addError.bind(null, 'Error')); - realtimeAPI.onMessage(handleMessage); - realtimeAPI.onCompletion(addError.bind(null, 'Not Connected to Server')); - realtimeAPI.keepAlive(); // Ping Server - - // Cleanup function to remove the event listeners when the component is unmounted - return () => { - realtimeAPI.disconnect(); - }; - }, []); - - useEffect(() => { - getConversationsList(); // todo: 和刷新订单会话页面有冲突 - getTemplates(); - return () => {}; - }, []); - - // useEffect(() => { - // if (!currentConversation.id && conversationsList.length > 0) { - // switchConversation(conversationsList[0]); - // } - // return () => {}; - // }, [conversationsList]); - - const poseConversationItemClose = async (item) => { - const res = await postJSON(`${API_HOST}/closeconversation`, { opisn: userId, conversationid: item.sn }); - } - - const getConversationsList = async () => { - const { result: data } = await fetchJSON(`${API_HOST}/getconversations`, { opisn: userId }); - // const _data = []; - const _data = testConversations; - const list = [..._data, ...data.map(ele => ({...ele, customer_name: ele.whatsapp_name.trim()}))]; - const dataMapped = list.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {}); - setConversationsList(list); - setActiveConversations({...dataMapped, ...activeConversations}); - console.log(list, dataMapped); - if (list && list.length) { - switchConversation(list[0]); - } - }; - - const [templatesList, setTemplatesList] = useState([]); - const getTemplates = async () => { - const data = await fetchJSON(`${API_HOST}/listtemplates`); - const canUseTemplates = (data?.result?.items || []).filter((_t) => _t.status !== 'REJECTED').map((ele) => ({ ...ele, components: groupBy(ele.components, (_c) => _c.type.toLowerCase()) })); - setTemplatesList(canUseTemplates); - }; - - const [customerOrderProfile, setCustomerProfile] = useState({}); - const getCustomerProfile = async (colisn) => { - const { result } = await fetchJSON(`${API_HOST}/getorderinfo`, { colisn }); - const data = result?.[0] || {}; - setCustomerProfile(data); - - if (!isEmpty(data.conversation)) { - setConversationsList((pre) => [...data.conversations, ...pre]); - setCurrentConversation(data.conversation[0]); - const thisCMapped = data.conversation.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {}); - setActiveConversations((pre) => ({ ...pre, ...thisCMapped })); - setMessages([]); // todo: 获取当前会话的历史消息 - } else { - // reset chat window - setMessages([]); - if (isEmpty(data.contact?.[0]?.whatsapp_phone_number)) { - setCurrentConversation({ sn: '', customer_name: '', coli_sn: '' }); - return false; - } - // 加入新会话 - const newChat = { - 'sn': uuid(), - // 'opi_sn': 354, - 'coli_sn': colisn, - 'whatsapp_phone_number': data.contact[0].whatsapp_phone_number, - "last_received_time": '', - "last_send_time": '', - 'unread_msg_count': 0, - 'whatsapp_name': data.contact[0].name, - 'customer_name': data.contact[0].name, - }; - setConversationsList((pre) => [...pre, newChat]); - setActiveConversations((pre) => ({ ...pre, [`${newChat.sn}`]: [] })); - setCurrentConversation(pick(newChat, ['sn', 'coli_sn', 'whatsapp_phone_number', 'whatsapp_name', 'customer_name'])); - } - }; - - const switchConversation = (cc) => { - setCurrentID(`${cc.sn}`); - setCurrentConversation({...cc, id: cc.sn, customer_name: cc.whatsapp_name.trim()}); - - if (isEmpty(cc.coli_sn) || cc.coli_sn === '0') { - setCustomerProfile({}); - } - }; - - // Get customer profile when switching conversation - useEffect(() => { - console.log('currentConversation', currentConversation); - setCurrentID(currentConversation.sn); - setMessages([...(activeConversations[currentConversation.sn] || [])]); - return () => {}; - }, [currentConversation]); - - /** - * ***************************************************************************************************** - * websocket -------------------------------------------------------------------------------------------- - * ***************************************************************************************************** - */ - const addError = (reason) => { - setErrors((prevErrors) => [...prevErrors, { reason }]); - }; - - const addMessageToConversations = (targetId, message) => { - setActiveConversations((prevList) => ({ - ...prevList, - [targetId]: [...(prevList[targetId] || []), message], - })); - // console.log('activeConversations', activeConversations); - if (targetId !== currentID) { - setConversationsList((prevList) => { - return prevList.map((ele) => { - if (ele.sn === targetId) { - return { ...ele, new_msgs: ele.new_msgs + 1, last_received_time: message.date }; - } - return ele; - }); - }); - } - }; - - useEffect(() => { - console.log(messages, 'messages'); - - return () => { - - } - }, [messages]) - - - const addMessage = (message) => { - addMessageToConversations(message.conversationid, message); - if (message.conversationid === currentID) { - setMessages((prevMessages) => [...prevMessages, message]); - } - }; - - const updateMessage = (message) => { - let targetMsgs; - setMessages((prevMessages) => { - targetMsgs = prevMessages.map(ele => { - if (ele.id === ele.actionId && ele.actionId === message.actionId) { - return {...ele, id: message.id, status: message.status, dateString: message.dateString}; - } - else if (ele.id === message.id) { - return {...ele, id: message.id, status: message.status, dateString: message.dateString}; - } - return ele; - }); - return targetMsgs; - }); - // 更新会话中的消息 - const targetId = message.conversationid; // currentConversationRef.current.sn; - setActiveConversations((prevList) => ({ - ...prevList, - [targetId]: targetMsgs, - })); - // 更新列表的时间 - setConversationsList((prevList) => { - return prevList.map((ele) => { - if (ele.sn === targetId) { - return { ...ele, new_msgs: ele.new_msgs + 1, last_received_time: message.date }; - } - return ele; - }); - }); - - }; - - const handleMessage = (data) => { - console.log('handleMessage------------------', ); - /** - * ! event handlers in JavaScript capture the environment (including variables) at the time they are defined, not when they are executed. - */ - const { errcode, errmsg, result } = data; - - if (!result) { - return false; - } - let resultType = result?.action || result.type; - if (errcode !== 0) { - // addError('Error Connecting to Server'); - resultType = 'error'; - } - console.log(resultType, 'result.type'); - const msgObj = receivedMsgTypeMapped[resultType].getMsg(result); - const msgRender = receivedMsgTypeMapped[resultType].contentToRender(msgObj); - const msgUpdate = receivedMsgTypeMapped[resultType].contentToUpdate(msgObj); - console.log('msgRender msgUpdate', msgRender, msgUpdate); - if ( ['whatsapp.message.updated', 'message', 'error'].includes(resultType)) { - updateMessage(msgUpdate); - // return false; - } - if ( ! isEmpty(msgRender)) { - addMessage(msgRender); - } - console.log('handleMessage*******************', ); - }; - - const sendMessage = (msgObj) => { - const contentToSend = sentMsgTypeMapped[msgObj.type].contentToSend(msgObj); - realtimeAPI.sendMessage({ ...contentToSend, opi_sn: userId }); - const contentToRender = sentMsgTypeMapped[msgObj.type].contentToRender(msgObj); - console.log(contentToRender, 'contentToRender sendMessage------------------'); - addMessage(contentToRender); - }; - - return { - errors, - messages, - conversationsList, - currentConversation, - sendMessage, - getConversationsList, - switchConversation, - templates: templatesList, // setTemplates, getTemplates, - customerOrderProfile, getCustomerProfile, - poseConversationItemClose - }; -}; - - - - - - - - - -// test: -const testConversations = [ - { - 'sn': 3001, - 'opi_sn': 354, - 'coli_sn': 0, - 'whatsapp_phone_number': '+8618777396951', - "last_received_time": new Date().toDateString(), - "last_send_time": new Date().toDateString(), - 'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2), - 'whatsapp_name': 'LiaoYijun', - 'customer_name': 'LiaoYijun', - }, - { - 'sn': 3002, - 'opi_sn': 354, - 'coli_sn': 0, - 'whatsapp_phone_number': '+8613317835586', - "last_received_time": new Date().toDateString(), - "last_send_time": new Date().toDateString(), - 'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2), - 'whatsapp_name': 'QinQianSheng', - 'customer_name': 'QinQianSheng', - }, - // { - // 'sn': 3003, - // 'opi_sn': 354, - // 'coli_sn': 240129003, - // 'whatsapp_phone_number': '+8618777396951', - // "last_received_time": new Date().toDateString(), - // "last_send_time": new Date().toDateString(), - // 'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2), - // 'whatsapp_name': 'LeiYuanTing', - // }, -]; diff --git a/src/views/Conversations/Components/Input/MediaUpload.jsx b/src/views/Conversations/Components/Input/MediaUpload.jsx index 8cb8f3e..62691da 100644 --- a/src/views/Conversations/Components/Input/MediaUpload.jsx +++ b/src/views/Conversations/Components/Input/MediaUpload.jsx @@ -3,7 +3,7 @@ import { useState } from 'react'; import { FileAddOutlined } from '@ant-design/icons'; import { v4 as uuid } from 'uuid'; import { API_HOST } from '@/config'; -import { whatsappSupportFileTypes } from '@/lib/msgUtils'; +import { whatsappSupportFileTypes } from '@/channel/whatsappUtils'; import { isEmpty, } from '@/utils/utils'; // import useConversationStore from '@/stores/ConversationStore'; diff --git a/src/views/Conversations/Components/Input/Template.jsx b/src/views/Conversations/Components/Input/Template.jsx index bd2402b..bb034c6 100644 --- a/src/views/Conversations/Components/Input/Template.jsx +++ b/src/views/Conversations/Components/Input/Template.jsx @@ -4,7 +4,7 @@ import { MessageOutlined, SendOutlined } from '@ant-design/icons'; import useAuthStore from '@/stores/AuthStore'; import useConversationStore from '@/stores/ConversationStore'; import { cloneDeep, getNestedValue, objectMapper, sortArrayByOrder } from '@/utils/utils'; -import { replaceTemplateString } from '@/lib/msgUtils'; +import { replaceTemplateString } from '@/channel/whatsappUtils'; import { isEmpty } from '@/utils/commons'; const splitTemplate = (template) => { diff --git a/src/views/Conversations/Components/InputComposer.jsx b/src/views/Conversations/Components/InputComposer.jsx index 707aa17..6cb54da 100644 --- a/src/views/Conversations/Components/InputComposer.jsx +++ b/src/views/Conversations/Components/InputComposer.jsx @@ -19,7 +19,7 @@ import { } from '@ant-design/icons'; import { isEmpty, } from '@/utils/utils'; import { v4 as uuid } from 'uuid'; -import { sentMsgTypeMapped, whatsappSupportFileTypes } from '@/lib/msgUtils'; +import { sentMsgTypeMapped, whatsappSupportFileTypes } from '@/channel/whatsappUtils'; import InputTemplate from './Input/Template'; import InputEmoji from './Input/Emoji'; import InputMediaUpload from './Input/MediaUpload';