订单进入会话, 获取新会话列表

dev/mobile
Lei OT 1 year ago
parent 6e4fc488a7
commit 22cf54f313

@ -5,104 +5,6 @@ import { parseRenderMessageList } from '@/lib/msgUtils';
const API_HOST = 'https://p9axztuwd7x8a7.mycht.cn/whatsapp_callback';
const NAME_SPACE = 'CONVERSATION/';
export const initWebsocket = (socket) => ({
type: NAME_SPACE + 'INIT_WEBSOCKET',
payload: socket,
});
export const closeWebsocket0 = () => ({
type: NAME_SPACE + 'CLOSE_WEBSOCKET',
payload: null,
});
export const updateWebsocketState = (v) => ({
type: NAME_SPACE + 'MODIFY_WEBSOCKET_STATE',
payload: v,
});
export const updateWebsocketRetrytimes = (v) => ({
type: NAME_SPACE + 'MODIFY_WEBSOCKET_RETRYTIMES',
payload: v,
});
export const receivedNewMessage = (targetId, message) => ({
type: NAME_SPACE + 'RECEIVED_NEW_MESSAGE',
payload: {
targetId,
message,
},
});
export const sentNewMessage = (message) => ({
type: NAME_SPACE + 'SENT_NEW_MESSAGE',
payload: {
targetId: message.conversationid,
message,
},
});
export const addError = (error) => {
return {
type: NAME_SPACE + 'ADD_ERROR',
payload: error,
};
};
export const receivedTemplates = (data) => ({
type: NAME_SPACE + 'SET_TEMPLATE_LIST',
payload: data,
});
export const receivedConversationList = (data) => {
return {
type: NAME_SPACE + 'SET_CONVERSATION_LIST',
payload: data,
};
};
export const addConversationList = (data) => {
return {
type: NAME_SPACE + 'ADD_TO_CONVERSATIONS_LIST',
payload: data,
};
};
export const delConversationitem = (data) => {
return {
type: NAME_SPACE + 'DEL_CONVERSATIONS_ITEM',
payload: data,
};
};
// export const updateConversationListItemNew = (message) => ({
// type: NAME_SPACE + 'UPDATE_CONVERSATION_LIST_ITEM_NEW',
// payload: message,
// });
export const receivedCustomerProfile = (data) => ({
type: NAME_SPACE + 'SET_CUSTOMER_ORDER_PROFILE',
payload: data,
});
/**
* @deprecated 在更新list时操作
*/
export const setActiveConversations = (obj) => ({
type: NAME_SPACE + 'SET_ACTIVE_CONVERSATIONS',
payload: obj,
});
export const setCurrentConversation = (obj) => ({
type: NAME_SPACE + 'SET_CURRENT_CONVERSATION',
payload: obj,
});
export const updateMessageItem = (message) => ({
type: NAME_SPACE + 'UPDATE_SENT_MESSAGE_ITEM',
payload: message,
});
export const receivedMessageList = (targetId, data) => ({
type: NAME_SPACE + 'RECEIVED_MESSAGE_LIST',
payload: { targetId, data },
})
export const setReplyTo = (data) => {
return {
type: NAME_SPACE + 'SET_REFERENCE_MSG',
payload: data,
};
};
export const fetchTemplates = async () => {
const data = await fetchJSON(`${API_HOST}/listtemplates`);
const canUseTemplates = (data?.result?.items || [])
@ -128,6 +30,13 @@ export const fetchCustomerProfile = async (colisn) => {
return data;
};
export const fetchOrderConversationsList = async (params) => {
const { errcode, result: data } = await fetchJSON(`${API_HOST}/getorderconversation`, params);
if (errcode !== 0) return [];
const list = data.map((ele) => ({ ...ele, customer_name: ele.whatsapp_name.trim() }));
return list;
};
export const fetchConversationItemClose = async (body) => {
const getParams = body ? new URLSearchParams(body).toString() : '';
const { result } = await fetchJSON(`${API_HOST}/closeconversation?${getParams}`);

@ -207,7 +207,7 @@ export const whatsappMsgTypeMapped = {
unsupported: { type: 'system', data: (msg) => ({ text: 'Message type is currently not supported.' }) },
reaction: {
type: 'text',
data: (msg) => ({ id: msg.wamid, text: msg.reaction?.emoji || msg.reaction?.text?.body || 'Reaction', reply: { message: '{content}', title: 'React from' } }), // todo:
data: (msg) => ({ id: msg.wamid, text: msg.reaction?.emoji || msg.reaction?.text?.body || 'Reaction', reply: { message: '{content}', title: 'React from', titleColor: '#1ba784' } }), // todo:
},
document: {
type: 'file',
@ -244,6 +244,16 @@ export const parseRenderMessageItem = (msg) => {
whatsapp_name: msg?.customerProfile?.name || '',
whatsapp_phone_number: msg.from,
whatsapp_msg_type: msg.type,
...(isEmpty(msg.context)
? {}
: {
reply: {
message: `${msg.context.id}`, // todo: msg.context.text?.body || msg.context.text,
title: msg?.customerProfile?.name || msg.from,
titleColor: "#128c7e",
},
origin: msg.context,
}),
};
};
/**
@ -275,7 +285,8 @@ export const parseRenderMessageList = (messages, conversationid = null) => {
: {
reply: {
message: msg.messageorigin_AsJOSN.text?.body || msg.messageorigin_AsJOSN.text,
title: msg.messageorigin_AsJOSN.senderName || msg.messageorigin_AsJOSN.from
title: msg.messageorigin_AsJOSN.senderName || '@', // msg.messageorigin_AsJOSN.from
titleColor: "#128c7e",
},
origin: msg.messageorigin_AsJOSN,
}),

@ -3,7 +3,6 @@ import ReactDOM from 'react-dom/client'
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import { AuthContext } from '@/stores/AuthContext'
import { ThemeContext } from '@/stores/ThemeContext'
import ConversationProvider from '@/views/Conversations/ConversationProvider'
import AuthApp from '@/views/AuthApp'
import Standlone from '@/views/Standlone'
import OrderFollow from '@/views/OrderFollow'
@ -43,9 +42,7 @@ ReactDOM.createRoot(document.getElementById('root')).render(
// <React.StrictMode>
<ThemeContext.Provider value={{ colorPrimary: '#1ba784', borderRadius: 4 }}>
<AuthContext.Provider value={{ loginUser: { userId: 354, username: '廖一军', accountList: [{OPI_Code:'LYJ'}, {OPI_Code:'LYJAH'}, {OPI_Code:'LYJGH'}] } }}>
{/* <ConversationProvider> */}
<RouterProvider router={router} fallbackElement={() => <div>Loading...</div>} />
{/* </ConversationProvider> */}
<RouterProvider router={router} fallbackElement={() => <div>Loading...</div>} />
</AuthContext.Provider>
</ThemeContext.Provider>
// </React.StrictMode>

@ -1,18 +0,0 @@
const initialState = {
websocket: null,
websocketOpened: null,
websocketRetrying: null,
websocketRetrytimes: null,
errors: [], // 错误信息
conversationsList: [], // 对话列表
templates: [],
customerOrderProfile: {},
activeConversations: {}, // 激活的对话的消息列表: { [conversationId]: [] }
currentConversation: {}, // 当前对话
referenceMsg: {},
};
export default initialState;

@ -1,156 +0,0 @@
import initialState from '@/records/ConversationState';
const NAME_SPACE = 'CONVERSATION/';
const ConversationReducer = (state = initialState, action) => {
switch (action.type) {
case NAME_SPACE + 'INIT_WEBSOCKET':
return { ...state, websocket: action.payload };
case NAME_SPACE + 'MODIFY_WEBSOCKET_STATE':
return { ...state, websocketOpened: action.payload, };
case NAME_SPACE + 'MODIFY_WEBSOCKET_RETRYTIMES':
return { ...state, websocketRetrytimes: action.payload, websocketRetrying: action.payload > 0 };
case NAME_SPACE + 'SET_CONVERSATION_LIST':{
const conversationsMapped = action.payload.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
return { ...state, conversationsList: action.payload, activeConversations: conversationsMapped };
}
case NAME_SPACE + 'ADD_TO_CONVERSATIONS_LIST':{
const { activeConversations } = state;
const conversationsIds = Object.keys(activeConversations);
const newConversations = action.payload.filter((conversation) => !conversationsIds.includes(`${conversation.sn}`));
const newConversationsMapped = newConversations.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
return {
...state,
conversationsList: [...newConversations, ...state.conversationsList],
activeConversations: { ...activeConversations, ...newConversationsMapped },
};
}
case NAME_SPACE + 'DEL_CONVERSATIONS_ITEM': {
const { conversationsList, activeConversations, currentConversation, customerOrderProfile } = state;
const targetId = action.payload.sn;
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
conversationsList.splice(targetIndex, 1);
return {
...state,
conversationsList: [...conversationsList],
activeConversations: { ...activeConversations, [`${targetId}`]: [] },
currentConversation: {},
customerOrderProfile: {},
};
}
case NAME_SPACE + 'SET_TEMPLATE_LIST':
return { ...state, templates: action.payload };
case NAME_SPACE + 'SET_CUSTOMER_ORDER_PROFILE':
return { ...state, customerOrderProfile: action.payload };
case NAME_SPACE + 'SET_CURRENT_CONVERSATION': {
// 清空未读
const { conversationsList } = state;
const targetId = action.payload.sn;
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
targetIndex !== -1 ? conversationsList.splice(targetIndex, 1, {
...conversationsList[targetIndex],
unread_msg_count: 0,
}) : null;
return { ...state, currentConversation: action.payload, conversationsList: [...conversationsList] };
}
case NAME_SPACE + 'SET_ACTIVE_CONVERSATIONS': {
const { activeConversations } = state;
return { ...state, activeConversations: { ...activeConversations, ...action.payload } };
}
case NAME_SPACE + 'UPDATE_SENT_MESSAGE_ITEM': {
console.log('UPDATE_SENT_MESSAGE_ITEM-----------------------------------------------------------------', action);
// 更新会话中的消息
const { activeConversations, conversationsList, } = state;
const message = action.payload;
const targetId = message.conversationid;
const targetMsgs = (activeConversations[String(targetId)] || []).map((ele) => {
// 更新状态
// * 已读的不再更新状态, 有时候投递结果在已读之后返回
if (ele.id === ele.actionId && ele.actionId === message.actionId) {
return { ...ele, id: message.id, status: ele.status === 'read' ? ele.status : message.status, dateString: message.dateString };
} else if (ele.id === message.id) {
return { ...ele, id: message.id, status: ele.status === 'read' ? ele.status : message.status, dateString: message.dateString };
}
return ele;
});
// 显示会话中其他客户端发送的消息
const targetMsgsIds = targetMsgs.map((ele) => ele.id);
if ( ! targetMsgsIds.includes(message.id)) {
targetMsgs.push(message);
}
// 更新列表的时间
if (message.type !== 'error') {
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
conversationsList.splice(targetIndex, 1, {
...conversationsList[targetIndex],
last_received_time: message.date,
});
}
return {
...state,
activeConversations: { ...state.activeConversations, [String(targetId)]: targetMsgs },
conversationsList: [...conversationsList],
};
}
case NAME_SPACE + 'RECEIVED_MESSAGE_LIST': {
const { targetId, data } = action.payload;
return {
...state,
activeConversations: { ...state.activeConversations, [String(targetId)]: data },
};
}
case NAME_SPACE + 'SENT_NEW_MESSAGE':
case NAME_SPACE + 'RECEIVED_NEW_MESSAGE': {
const { activeConversations, conversationsList, currentConversation } = state;
const { targetId, message } = action.payload;
const targetMsgs = activeConversations[String(targetId)] || [];
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
const newConversation =
targetId !== -1
? {
...conversationsList[targetIndex],
last_received_time: message.date,
unread_msg_count:
String(targetId) !== String(currentConversation.sn) && message.sender !== 'me'
? conversationsList[targetIndex].unread_msg_count + 1
: conversationsList[targetIndex].unread_msg_count,
}
: {
...message,
sn: targetId,
last_received_time: message.date,
unread_msg_count: message.sender === 'me' ? 0 : 1,
};
conversationsList.splice(targetIndex, 1);
conversationsList.unshift(newConversation);
return {
...state,
activeConversations: { ...activeConversations, [String(targetId)]: [...targetMsgs, message] },
conversationsList: [...conversationsList],
currentConversation: {
...state.currentConversation,
last_received_time: String(targetId) === String(currentConversation.sn) ? message.date : currentConversation.last_received_time,
},
};
}
case NAME_SPACE + 'SET_REFERENCE_MSG':
return {...state, referenceMsg: action.payload};
case NAME_SPACE + 'ADD_ERROR': {
console.log('add error', state.errors, action.payload);
const prelist = state.errors || [];
return { ...state, errors: [...prelist, action.payload] };
}
default:
// throw new Error(`Unknown action: ${action.type}`);
return state;
}
};
export default ConversationReducer;

@ -1,12 +0,0 @@
import {createContext, useContext} from 'react';
export const ConversationContext = createContext();
export const useConversationContext = () => useContext(ConversationContext);
export const ConversationStateContext = createContext();
export const ConversationDispatchContext = createContext();
export const useConversationState = () => useContext(ConversationStateContext);
export const useConversationDispatch = () => useContext(ConversationDispatchContext);

@ -122,6 +122,9 @@ export const conversationSlice = (set, get) => ({
conversationsList: [],
currentConversation: {},
/**
* @deprecated
*/
setConversationsList: (conversationsList) => {
const conversationsMapped = conversationsList.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
return set({ conversationsList, activeConversations: conversationsMapped });
@ -251,10 +254,10 @@ export const useConversationStore = create(devtools((set, get) => ({
// side effects
fetchInitialData: async (userId) => {
olog('fetch init');
const { setConversationsList, setTemplates } = get();
const { addToConversationList, setTemplates } = get();
const conversationsList = await fetchConversationsList({ opisn: userId });
setConversationsList(conversationsList);
addToConversationList(conversationsList);
const templates = await fetchTemplates();
setTemplates(templates);

@ -1,5 +1,6 @@
import { useEffect } from 'react';
import { Layout, Spin } from 'antd';
import { useEffect, useState } from 'react';
import { Layout, Spin, Button } from 'antd';
import { RightCircleOutlined, RightOutlined, MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
// import { useParams, useNavigate } from 'react-router-dom';
import MessagesHeader from './Components/MessagesHeader';
import Messages from './Components/Messages';
@ -27,31 +28,56 @@ const ChatWindow = () => {
return () => {};
}, []);
const [collapsedLeft, setCollapsedLeft] = useState(false);
const [collapsedRight, setCollapsedRight] = useState(false);
return (
<Spin spinning={false} tip={'正在连接...'}>
<Layout className='h-screen chatwindow-wrapper' style={{ maxHeight: 'calc(100% - 198px)', height: 'calc(100% - 198px)' }}>
<Sider width={240} theme={'light'} className='h-full overflow-y-auto' style={{ maxHeight: 'calc(100vh - 198px)', height: 'calc(100vh - 198px)' }}>
<Layout hasSider className='h-screen chatwindow-wrapper' style={{ maxHeight: 'calc(100% - 198px)', height: 'calc(100% - 198px)' }}>
<Sider
width={240}
theme={'light'}
className='h-full overflow-y-auto'
style={{ maxHeight: 'calc(100vh - 198px)', height: 'calc(100vh - 198px)' }}
collapsible={true}
breakpoint='xxl'
collapsedWidth={73}
collapsed={collapsedLeft}
onBreakpoint={(broken) => {
console.log('xxxxxxxxxxxxxxxxxxxxxx', broken);
}}
trigger={null}>
<ConversationsList />
</Sider>
<Content style={{ maxHeight: 'calc(100vh - 198px)', height: 'calc(100vh - 198px)' }}>
<Layout className='h-full'>
<Header className='ant-layout-sider-light ant-card h-auto'>
<Header className='ant-layout-sider-light ant-card h-auto flex justify-between items-center'>
<Button type='text' icon={collapsedLeft ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />} onClick={() => setCollapsedLeft(!collapsedLeft)} className=' rounded-none rounded-l' />
<MessagesHeader />
<Button type='text' icon={collapsedRight ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />} onClick={() => setCollapsedRight(!collapsedRight)} className=' rounded-none rounded-r' />
</Header>
<Content style={{ maxHeight: '74vh', height: '74vh' }}>
<Content className="flex-grow bg-whatsapp-bg" >
<div className='h-full overflow-y-auto'>
<Messages />
</div>
</Content>
<Footer className='ant-layout-sider-light p-1 max-h-32'>
<Footer className='ant-layout-sider-light p-0'>
<InputComposer />
</Footer>
</Layout>
</Content>
<Sider width={300} theme={'light'} className='h-full overflow-y-auto' style={{ maxHeight: 'calc(100vh - 198px)', height: 'calc(100vh - 198px)' }}>
<Sider
width={300}
theme={'light'}
className=' overflow-y-auto'
style={{ maxHeight: 'calc(100vh - 198px)', height: 'calc(100vh - 198px)' }}
collapsible={true}
breakpoint='xxl'
collapsedWidth={0}
trigger={null}
collapsed={collapsedRight}>
<CustomerProfile />
</Sider>
</Layout>

@ -1,10 +1,10 @@
import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useParams, useNavigate, useLocation } from 'react-router-dom';
import { Button, Dropdown } from 'antd';
import { MoreOutlined } from '@ant-design/icons';
import { useAuthContext } from '@/stores/AuthContext';
import {
fetchConversationsList,
fetchOrderConversationsList,
fetchConversationItemClose,
fetchMessages,
} from '@/actions/ConversationActions';
@ -44,6 +44,8 @@ const CDropdown = (props) => {
* []
*/
const Conversations = () => {
const { state: orderRow } = useLocation()
const { coli_guest_WhatsApp } = orderRow || {};
const { order_sn } = useParams();
const navigate = useNavigate();
const { loginUser } = useAuthContext();
@ -60,7 +62,7 @@ const Conversations = () => {
title: item.whatsapp_name.trim() || item.whatsapp_phone_number,
// subtitle: item.whatsapp_phone_number,
// subtitle: item.lastMessage,
date: item.last_received_time, // last_send_time // todo: GMT+8
date: item.last_received_time, // last_send_time
unread: item.unread_msg_count,
// showMute: true,
// muted: false,
@ -76,21 +78,23 @@ const Conversations = () => {
return () => {};
}, [conversationsList, currentConversation]);
const [shouldFetchCList, setShouldFetchCList] = useState(true);
useEffect(() => {
if (order_sn) {
// getOrderConversationList(order_sn);
// debug: reset chat window
setCurrentConversation({ sn: '', customer_name: '', coli_sn: order_sn });
if (order_sn && shouldFetchCList) {
getOrderConversationList(order_sn);
}
return () => {};
}, [order_sn]);
}, [order_sn, shouldFetchCList]);
const getOrderConversationList = async (colisn) => {
const data = await fetchConversationsList({ opisn: userId, colisn });
const { whatsapp_phone_number } = switchToC;
const whatsappID = coli_guest_WhatsApp || whatsapp_phone_number || '';
const data = await fetchOrderConversationsList({ opisn: userId, colisn: colisn, whatsappid: whatsappID });
if (!isEmpty(data)) {
addToConversationList(data);
switchConversation(data[0]);
const ifCurrent = data.findIndex((item) => item.sn === currentConversation.sn);
switchConversation(data[ifCurrent === -1 ? 0 : ifCurrent]);
} else {
// reset chat window
setCurrentConversation({ sn: '', customer_name: '', coli_sn: order_sn });
@ -109,31 +113,24 @@ const Conversations = () => {
setCurrentConversation(item);
};
const [switchToC, setSwitchToC] = useState({});
const onSwitchConversation = (item) => {
if (item.coli_sn) {
navigate(`/order/chat/${item.coli_sn}`, { replace: true });
setSwitchToC(item);
setShouldFetchCList(false);
} else {
navigate(`/order/chat`, { replace: true });
}
switchConversation(item);
};
// const handleConversationItemClose = async (item) => {
// console.log('invoke close', item);
// const data = await postConversationItemClose({ conversationid: item.sn, opisn: userId });
// };
return (
<>
<ChatList
className=''
className=' overflow-x-hidden'
dataSource={chatlist}
onClick={(item) => onSwitchConversation(item)}
// onContextMenu={(item, i, e) => {
// console.log(item, i, e);
// return ( <p>ppp</p> )
// }}
// onClickMute={handleConversationItemClose}
/>
</>
);

@ -6,24 +6,27 @@ import { useShallow } from 'zustand/react/shallow';
const Messages = () => {
const { currentConversation, setReferenceMsg } = useConversationStore();
const activeMessages = useConversationStore(useShallow(state => currentConversation.sn ? state.activeConversations[currentConversation.sn] : []));
const activeMessages = useConversationStore(useShallow((state) => (currentConversation.sn ? state.activeConversations[currentConversation.sn] : [])));
const messagesList = useMemo(() => (activeMessages || []).map(message => ({
...message,
key: message.id,
position: message.sender === 'me' ? 'right' : 'left',
onOpen: () => handlePreview(message),
...(message.sender === 'me' ? {
styles: { backgroundColor: '#ccd4ae' } ,
notchStyle: { fill: '#ccd4ae'},
replyButton: ['text'].includes(message.whatsapp_msg_type) && message.status !== 'failed' ? true : false,
onReplyClick: () => (setReferenceMsg(message)),
className: 'whatsappme-container whitespace-pre-wrap',
} : {
replyButton: ['text'].includes(message.whatsapp_msg_type) ? true : false,
onReplyClick: () => (setReferenceMsg(message)),
}),
})), [activeMessages, currentConversation.sn]);
const messagesList = useMemo(
() =>
(activeMessages || []).map((message) => ({
...message,
key: message.id,
position: message.sender === 'me' ? 'right' : 'left',
...(message.sender === 'me'
? {
styles: { backgroundColor: '#ccd4ae' },
notchStyle: { fill: '#ccd4ae' },
replyButton: ['text'].includes(message.whatsapp_msg_type) && message.status !== 'failed' ? true : false,
className: 'whatsappme-container whitespace-pre-wrap',
}
: {
replyButton: ['text'].includes(message.whatsapp_msg_type) ? true : false,
}),
})),
[activeMessages, currentConversation.sn]
);
console.log('messagesList----------------------------------------------------', messagesList);
const messagesEndRef = useRef(null);
@ -48,9 +51,7 @@ const Messages = () => {
return (
<div>
{messagesList.map((message, index) => (
<MessageBox key={message.key}
{...message}
/>
<MessageBox key={message.key} {...message} onReplyClick={() => setReferenceMsg(message)} onOpen={() => handlePreview(message)} />
))}
<Image src={previewSrc} preview={{ visible: previewVisible, src: previewSrc, onClose: onPreviewClose }} />
<div ref={messagesEndRef}></div>

@ -11,7 +11,7 @@ const MessagesHeader = () => {
<>
{websocketOpened===false && <Alert type='error' message='断开连接' banner />}
{websocketRetrying && websocketRetrytimes > 0 && <Alert type={'warning'} message={`正在重连, ${websocketRetrytimes}次...`} banner icon={<LoadingOutlined />} />}
<Flex gap={16} className='p-1'>
<Flex gap={16} className='p-1 flex-auto'>
{currentConversation.customer_name && <Avatar src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${currentConversation.customer_name}`} />}
<Flex flex={'1'} justify='space-between'>
<Flex vertical={true} justify='space-between'>

@ -1,102 +0,0 @@
import { useContext, useReducer, useEffect } from 'react';
import { ConversationStateContext, ConversationDispatchContext } from '@/stores/ConversationContext';
import ConversationReducer from '@/reducers/ConversationReducer';
import {
initWebsocket,
updateWebsocketState,
updateWebsocketRetrytimes,
addError,
fetchConversationsList,
fetchTemplates,
receivedConversationList,
receivedTemplates,
updateMessageItem,
receivedNewMessage,
} from '@/actions/ConversationActions';
import initialState from '@/records/ConversationState';
import { AuthContext } from '@/stores/AuthContext';
import { RealTimeAPI } from '@/lib/realTimeAPI';
import { receivedMsgTypeMapped } from '@/lib/msgUtils';
import { isEmpty } from '@/utils/utils';
// const WS_URL = 'ws://202.103.68.144:8888/whatever/';
// const WS_URL = 'ws://120.79.9.217:10022/whatever/';
const WS_URL = 'wss://p9axztuwd7x8a7.mycht.cn/whatsapp_callback'; // prod:
const ConversationProvider = ({ children }) => {
const { loginUser } = useContext(AuthContext);
const { userId } = loginUser;
const [state, dispatch] = useReducer(ConversationReducer, { ...initialState, websocket: null });
console.log('ConversationProvider', state, dispatch);
// useEffect(() => {
// console.log('invoke provider');
// const realtimeAPI = new RealTimeAPI(
// {
// url: `${WS_URL}?opisn=${userId || ''}&_spam=${Date.now().toString()}`,
// protocol: 'WhatsApp',
// },
// () => {dispatch(updateWebsocketState(true)); dispatch(updateWebsocketRetrytimes(0));},
// () => dispatch(updateWebsocketState(false)),
// (n) => dispatch(updateWebsocketRetrytimes(n))
// );
// realtimeAPI.onError(() => dispatch(addError('Error')));
// realtimeAPI.onMessage(handleMessage);
// realtimeAPI.onCompletion(() => dispatch(addError('Connection broken')));
// dispatch(initWebsocket(realtimeAPI));
// return () => {
// realtimeAPI.disconnect();
// };
// }, []);
// useEffect(() => {
// fetchConversationsList({ opisn: userId }).then((data) => {
// dispatch(receivedConversationList(data));
// });
// fetchTemplates().then((data) => dispatch(receivedTemplates(data)));
// return () => {};
// }, []);
const handleMessage = (data) => {
console.log('handleMessage------------------');
console.log(data);
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)) {
dispatch(updateMessageItem(msgUpdate));
// return false;
}
if (!isEmpty(msgRender)) {
dispatch(receivedNewMessage(msgRender.conversationid, msgRender));
}
console.log('handleMessage*******************');
};
// return <ConversationContext.Provider value={{ ...state, dispatch }}>{children}</ConversationContext.Provider>;
return (
<ConversationStateContext.Provider value={{ ...state }}>
<ConversationDispatchContext.Provider value={dispatch}>{children}</ConversationDispatchContext.Provider>
</ConversationStateContext.Provider>
);
};
export default ConversationProvider;

@ -12,8 +12,9 @@ export default {
dark: '#075E54',
second: '#128c7e',
gossip: '#dcf8c6',
bg: '#ece5dd',
me: '#ccd5ae',
bg: '#ece5dd', // '#efeae2' '#eae6df' '#d1d7db'
bgdark: '#0b141a',
me: '#ccd5ae', // '#d9fdd3'
},
'primary': '#1ba784',
},

Loading…
Cancel
Save