@droppii-org/chat-sdk 0.0.19 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/components/chatBubble/ChatBubble.d.ts.map +1 -0
  2. package/dist/components/{ChatBubble.js → chatBubble/ChatBubble.js} +2 -2
  3. package/dist/components/conversation/DeskConversationList.d.ts +1 -2
  4. package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
  5. package/dist/components/conversation/DeskConversationList.js +107 -148
  6. package/dist/components/message/MessageList.d.ts.map +1 -1
  7. package/dist/components/message/MessageList.js +46 -14
  8. package/dist/constants/index.d.ts +2 -0
  9. package/dist/constants/index.d.ts.map +1 -0
  10. package/dist/constants/index.js +1 -0
  11. package/dist/constants/sdk.d.ts.map +1 -1
  12. package/dist/constants/sdk.js +3 -1
  13. package/dist/context/ChatContext.d.ts +1 -1
  14. package/dist/context/ChatContext.d.ts.map +1 -1
  15. package/dist/context/ChatContext.js +42 -7
  16. package/dist/hooks/conversation/useConversation.d.ts +2 -1
  17. package/dist/hooks/conversation/useConversation.d.ts.map +1 -1
  18. package/dist/hooks/conversation/useConversation.js +18 -16
  19. package/dist/hooks/message/useMessage.d.ts +3 -0
  20. package/dist/hooks/message/useMessage.d.ts.map +1 -1
  21. package/dist/hooks/message/useMessage.js +36 -4
  22. package/dist/hooks/message/useSendMessage.d.ts +5 -2
  23. package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
  24. package/dist/hooks/message/useSendMessage.js +21 -8
  25. package/dist/hooks/zustand/useMessageStore.d.ts +9 -0
  26. package/dist/hooks/zustand/useMessageStore.d.ts.map +1 -0
  27. package/dist/hooks/zustand/useMessageStore.js +8 -0
  28. package/dist/index.d.ts +3 -3
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +3 -3
  31. package/dist/screens/chatBubble/index.d.ts +10 -0
  32. package/dist/screens/chatBubble/index.d.ts.map +1 -0
  33. package/dist/screens/chatBubble/index.js +12 -0
  34. package/dist/screens/deskMessage/index.d.ts.map +1 -0
  35. package/dist/screens/deskMessage/index.js +22 -0
  36. package/dist/styles/global.css +1 -1
  37. package/dist/types/chat.d.ts +15 -1
  38. package/dist/types/chat.d.ts.map +1 -1
  39. package/dist/types/chat.js +6 -1
  40. package/package.json +10 -2
  41. package/dist/assets/openIM.wasm +0 -0
  42. package/dist/components/ChatBubble.d.ts.map +0 -1
  43. package/dist/screens/desk-message/index.d.ts.map +0 -1
  44. package/dist/screens/desk-message/index.js +0 -14
  45. /package/dist/components/{ChatBubble.d.ts → chatBubble/ChatBubble.d.ts} +0 -0
  46. /package/dist/screens/{desk-message → deskMessage}/index.d.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatBubble.d.ts","sourceRoot":"","sources":["../../../src/components/chatBubble/ChatBubble.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,UAAU,eAAe;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,UAAU,GAAI,uDAKjB,eAAe,4CAmDjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -3,8 +3,8 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
3
3
  import { useState } from "react";
4
4
  import { FloatButton, Drawer } from "antd";
5
5
  import { MessageOutlined, CloseOutlined } from "@ant-design/icons";
6
- import MessageList from "./message/MessageList";
7
- import { useConversationDetail } from "../hooks/conversation/useConversation";
6
+ import MessageList from "../message/MessageList";
7
+ import { useConversationDetail } from "../../hooks/conversation/useConversation";
8
8
  const ChatBubble = ({ conversationId, sourceID, sessionType, className, }) => {
9
9
  const { conversationDetail } = useConversationDetail({
10
10
  sourceID,
@@ -1,8 +1,7 @@
1
1
  interface DeskConversationListProps {
2
2
  onConversationSelect?: (conversationId: string, threadId: string) => void;
3
- selectedConversationId?: string;
4
3
  className?: string;
5
4
  }
6
- declare const DeskConversationList: ({ onConversationSelect, selectedConversationId, className, }: DeskConversationListProps) => import("react/jsx-runtime").JSX.Element;
5
+ declare const DeskConversationList: ({ onConversationSelect, className, }: DeskConversationListProps) => import("react/jsx-runtime").JSX.Element;
7
6
  export default DeskConversationList;
8
7
  //# sourceMappingURL=DeskConversationList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AAkHA,UAAU,yBAAyB;IACjC,oBAAoB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmDD,QAAA,MAAM,oBAAoB,GAAI,8DAI3B,yBAAyB,4CAiK3B,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AAwGA,UAAU,yBAAyB;IACjC,oBAAoB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,oBAAoB,GAAI,sCAG3B,yBAAyB,4CAiL3B,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -1,168 +1,127 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useEffect } from "react";
3
+ import { useState, useEffect, useCallback } from "react";
4
4
  import { useRouter, useSearchParams, usePathname } from "next/navigation";
5
+ import { Input, Avatar, Badge, Empty } from "antd";
6
+ import { SessionType } from "@openim/wasm-client-sdk";
5
7
  import { useConversationList } from "../../hooks/conversation/useConversation";
6
8
  import { Icon } from "../icon";
7
- const mockConversations = [
8
- {
9
- id: "1",
10
- threadId: "thread_001",
11
- name: "Phương Huyền (phhuyen2110)",
12
- username: "phhuyen2110",
13
- avatar: "https://i.pinimg.com/736x/55/e5/ed/55e5edbb1a5b5f6e4f3cefc98de629ca.jpg",
14
- lastMessage: "Customer: hi Livechat Obefe",
15
- timestamp: "27/07",
16
- unreadCount: 1,
17
- isOnline: true,
18
- status: "unassigned",
19
- source: "obefe",
20
- },
21
- {
22
- id: "2",
23
- threadId: "thread_002",
24
- name: "Phương Huyền (phhuyen2110)",
25
- username: "phhuyen2110",
26
- avatar: "https://i.pinimg.com/736x/55/e5/ed/55e5edbb1a5b5f6e4f3cefc98de629ca.jpg",
27
- lastMessage: "Customer: hi Livechat Obefe",
28
- timestamp: "27/07",
29
- unreadCount: 1,
30
- isOnline: true,
31
- status: "slow",
32
- source: "obefe",
33
- },
34
- {
35
- id: "3",
36
- threadId: "thread_003",
37
- name: "Phương Huyền (phhuyen2110)",
38
- username: "phhuyen2110",
39
- avatar: "https://i.pinimg.com/736x/55/e5/ed/55e5edbb1a5b5f6e4f3cefc98de629ca.jpg",
40
- lastMessage: "Customer: hi Livechat Obefe",
41
- timestamp: "27/07",
42
- unreadCount: 1,
43
- isOnline: true,
44
- status: "waiting",
45
- source: "obefe",
46
- },
47
- {
48
- id: "4",
49
- threadId: "thread_004",
50
- name: "Phương Huyền (phhuyen2110)",
51
- username: "phhuyen2110",
52
- avatar: "https://i.pinimg.com/736x/55/e5/ed/55e5edbb1a5b5f6e4f3cefc98de629ca.jpg",
53
- lastMessage: "Customer: hi Livechat Obefe",
54
- timestamp: "27/07",
55
- unreadCount: 1,
56
- isOnline: true,
57
- status: "not_replied",
58
- source: "obefe",
59
- },
60
- {
61
- id: "5",
62
- threadId: "thread_005",
63
- name: "Phương Huyền (phhuyen2110)",
64
- username: "phhuyen2110",
65
- avatar: "https://i.pinimg.com/736x/55/e5/ed/55e5edbb1a5b5f6e4f3cefc98de629ca.jpg",
66
- lastMessage: "Customer: hi Livechat Obefe",
67
- timestamp: "27/07",
68
- unreadCount: 1,
69
- isOnline: true,
70
- status: "processing",
71
- source: "obefe",
72
- },
73
- {
74
- id: "6",
75
- threadId: "thread_006",
76
- name: "Phương Huyền (phhuyen2110)",
77
- username: "phhuyen2110",
78
- avatar: "https://i.pinimg.com/736x/55/e5/ed/55e5edbb1a5b5f6e4f3cefc98de629ca.jpg",
79
- lastMessage: "Customer: hi Livechat Obefe",
80
- timestamp: "27/07",
81
- unreadCount: 1,
82
- isOnline: true,
83
- status: "closed",
84
- source: "obefe",
85
- },
86
- ];
87
- const getStatusIcon = (status) => {
88
- switch (status) {
89
- case "unassigned":
90
- return {
91
- icon: "user-del-o",
92
- bgColor: "bg-red-100",
93
- iconColor: "text-red-500",
94
- };
95
- case "slow":
96
- return {
97
- icon: "warning-square-o",
98
- bgColor: "bg-orange-100",
99
- iconColor: "text-orange-500",
100
- };
101
- case "waiting":
102
- return {
103
- icon: "time-circle-o",
104
- bgColor: "bg-yellow-100",
105
- iconColor: "text-yellow-600",
106
- };
107
- case "not_replied":
108
- return {
109
- icon: "arrow-reply-o",
110
- bgColor: "bg-orange-100",
111
- iconColor: "text-orange-500",
112
- };
113
- case "processing":
114
- return {
115
- icon: "play-b",
116
- bgColor: "bg-blue-100",
117
- iconColor: "text-blue-500",
118
- };
119
- case "paused":
120
- return {
121
- icon: "pause-b",
122
- bgColor: "bg-gray-100",
123
- iconColor: "text-gray-500",
124
- };
125
- case "closed":
126
- return {
127
- icon: "check-b",
128
- bgColor: "bg-green-100",
129
- iconColor: "text-green-500",
130
- };
131
- default:
132
- return null;
9
+ import { useChatContext } from "../../context/ChatContext";
10
+ import useMessageStore from "../../hooks/zustand/useMessageStore";
11
+ import { useMessage } from "../../hooks/message/useMessage";
12
+ const parseLatestMessage = (latestMsg, currentUserId) => {
13
+ var _a;
14
+ if (!latestMsg)
15
+ return "";
16
+ try {
17
+ const msgData = JSON.parse(latestMsg);
18
+ // Check for text message (textElem)
19
+ if ((_a = msgData.textElem) === null || _a === void 0 ? void 0 : _a.content) {
20
+ const isMe = currentUserId && msgData.sendID === currentUserId;
21
+ const sender = isMe ? "Me" : (msgData === null || msgData === void 0 ? void 0 : msgData.senderNickname) || msgData.sendID;
22
+ return `${sender}: ${msgData.textElem.content}`;
23
+ }
24
+ // TODO: Handle other message types (fileElem, videoElem, etc.)
25
+ // For now, return empty string for non-text messages
26
+ // This can be enhanced later to show appropriate previews
27
+ return "Tin nhắn không khả dụng";
133
28
  }
29
+ catch (error) {
30
+ console.error("Error parsing latest message:", error);
31
+ return "";
32
+ }
33
+ };
34
+ // Utility function to format timestamp
35
+ const formatTimestamp = (timestamp) => {
36
+ if (!timestamp)
37
+ return "";
38
+ const date = new Date(timestamp);
39
+ const now = new Date();
40
+ const diffInMs = now.getTime() - date.getTime();
41
+ const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24));
42
+ if (diffInDays === 0) {
43
+ // Today - show time
44
+ return date.toLocaleTimeString("vi-VN", {
45
+ hour: "2-digit",
46
+ minute: "2-digit",
47
+ hour12: false,
48
+ });
49
+ }
50
+ else if (diffInDays === 1) {
51
+ // Yesterday
52
+ return "Hôm qua";
53
+ }
54
+ else if (diffInDays < 7) {
55
+ // This week - show day name
56
+ return date.toLocaleDateString("vi-VN", { weekday: "long" });
57
+ }
58
+ else {
59
+ // Older - show date
60
+ return date.toLocaleDateString("vi-VN", {
61
+ day: "2-digit",
62
+ month: "2-digit",
63
+ });
64
+ }
65
+ };
66
+ // Transform API data to UI-friendly format
67
+ const transformConversationData = (apiData, currentUserId) => {
68
+ return apiData.map((conv) => (Object.assign(Object.assign({}, conv), { id: conv.conversationID, threadId: conv.conversationID, name: conv.showName || "Unknown User", username: conv.userID || conv.groupID || "", avatar: conv.faceURL ||
69
+ "https://i.pinimg.com/736x/55/e5/ed/55e5edbb1a5b5f6e4f3cefc98de629ca.jpg", lastMessage: parseLatestMessage(conv.latestMsg, currentUserId), timestamp: formatTimestamp(conv.latestMsgSendTime), unreadCount: conv.unreadCount, isOnline: true, source: conv.conversationType === 3 ? "group" : "direct" })));
134
70
  };
135
- const DeskConversationList = ({ onConversationSelect, selectedConversationId, className = "", }) => {
136
- const { conversationList } = useConversationList();
71
+ const DeskConversationList = ({ onConversationSelect, className = "", }) => {
137
72
  const [searchQuery, setSearchQuery] = useState("");
138
73
  const router = useRouter();
139
74
  const pathname = usePathname();
140
75
  const searchParams = useSearchParams();
141
- console.log(conversationList);
142
- const currentThreadId = searchParams.get("threadId");
143
- const [selectedThreadId, setSelectedThreadId] = useState(currentThreadId);
144
- useEffect(() => {
145
- setSelectedThreadId(currentThreadId);
146
- }, [currentThreadId]);
147
- const conversations = mockConversations;
76
+ const { user } = useChatContext();
77
+ const selectedThreadId = useMessageStore((state) => state.selectedThreadId);
78
+ const setSelectedThreadId = useMessageStore((state) => state.setSelectedThreadId);
79
+ const setSelectedSourceId = useMessageStore((state) => state.setSelectedSourceId);
80
+ const { markConversationMessageAsRead } = useMessage(selectedThreadId);
81
+ const { conversationList } = useConversationList(selectedThreadId);
82
+ // Transform real conversation data from the API
83
+ const conversations = transformConversationData(conversationList || [], user === null || user === void 0 ? void 0 : user.userID);
148
84
  const filteredConversations = conversations.filter((conv) => conv.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
149
85
  conv.lastMessage.toLowerCase().includes(searchQuery.toLowerCase()));
150
86
  const handleConversationClick = (conversation) => {
151
87
  const newSearchParams = new URLSearchParams(searchParams);
152
- newSearchParams.set("threadId", conversation.threadId);
88
+ newSearchParams.set("threadId", conversation.id);
153
89
  router.push(`${pathname}?${newSearchParams.toString()}`);
154
- setSelectedThreadId(conversation.threadId);
155
- onConversationSelect === null || onConversationSelect === void 0 ? void 0 : onConversationSelect(conversation.id, conversation.threadId);
90
+ setSelectedThreadId(conversation.id);
91
+ onConversationSelect === null || onConversationSelect === void 0 ? void 0 : onConversationSelect(conversation.id, conversation.id);
156
92
  };
157
- return (_jsxs("div", { className: `flex flex-col h-full bg-white border-r border-gray-200 ${className}`, children: [_jsx("div", { className: "p-3 border-b border-gray-200", children: _jsxs("div", { className: "relative", children: [_jsx(Icon, { icon: "search-o", size: 18, className: "absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" }), _jsx("input", { type: "text", placeholder: "T\u00ECm ki\u1EBFm", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full pl-10 pr-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm" })] }) }), _jsxs("div", { className: "flex-1 overflow-y-auto", children: [filteredConversations.map((conversation) => (_jsxs("div", { onClick: () => handleConversationClick(conversation), className: `relative p-3 border-b border-gray-100 hover:bg-gray-50 cursor-pointer transition-colors ${selectedThreadId === conversation.threadId
93
+ const onSetSelectedSourceId = useCallback(() => {
94
+ const selectedConversation = conversations.findIndex((conv) => conv.id === selectedThreadId);
95
+ if (selectedConversation !== -1) {
96
+ const conversation = conversations[selectedConversation];
97
+ const sourceId = conversation.conversationType === SessionType.Group
98
+ ? conversation.groupID
99
+ : conversation.userID;
100
+ setSelectedSourceId(sourceId);
101
+ }
102
+ }, [conversationList, selectedThreadId]);
103
+ useEffect(() => {
104
+ const threadId = searchParams.get("threadId");
105
+ if (threadId) {
106
+ setSelectedThreadId(threadId);
107
+ }
108
+ else if (conversations.length > 0) {
109
+ setSelectedThreadId(conversations[0].id);
110
+ const newSearchParams = new URLSearchParams(searchParams);
111
+ newSearchParams.set("threadId", conversations[0].id);
112
+ router.replace(`${pathname}?${newSearchParams.toString()}`);
113
+ }
114
+ }, [searchParams, conversations.length]);
115
+ useEffect(() => {
116
+ if (!!selectedThreadId) {
117
+ markConversationMessageAsRead();
118
+ onSetSelectedSourceId();
119
+ }
120
+ }, [selectedThreadId, onSetSelectedSourceId, markConversationMessageAsRead]);
121
+ return (_jsxs("div", { className: `flex flex-col h-full bg-white border-r border-gray-200 ${className}`, children: [_jsx("div", { className: "p-3 border-b border-gray-200", children: _jsx(Input, { placeholder: "T\u00ECm ki\u1EBFm", prefix: _jsx(Icon, { icon: "search-o", size: 18, className: "text-gray-400" }), value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "rounded-lg" }) }), _jsxs("div", { className: "flex-1 overflow-y-auto", children: [filteredConversations.map((conversation) => (_jsxs("div", { onClick: () => handleConversationClick(conversation), className: `relative p-3 border-b border-gray-100 hover:bg-gray-50 cursor-pointer transition-colors ${selectedThreadId === conversation.threadId
158
122
  ? "bg-blue-50"
159
- : "bg-white"}`, children: [selectedThreadId === conversation.threadId && (_jsx("div", { className: "absolute left-0 top-0 bottom-0 w-1 bg-blue-500" })), _jsxs("div", { className: "flex items-start gap-3", children: [_jsxs("div", { className: "relative flex-shrink-0", children: [_jsx("img", { src: conversation.avatar, alt: conversation.name, className: "w-12 h-12 rounded-full object-cover" }), conversation.isOnline && (_jsx("div", { className: "absolute -bottom-0.5 -right-0.5 w-4 h-4 bg-green-500 border-2 border-white rounded-full" }))] }), _jsx("div", { className: "flex-1 min-w-0", children: _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-semibold text-gray-900 text-sm truncate", children: conversation.name }), _jsx("p", { className: "text-xs text-gray-500 truncate mt-0.5", children: conversation.lastMessage })] }), _jsxs("div", { className: "flex flex-col items-end gap-1 ml-2", children: [_jsx("span", { className: "text-xs text-gray-400", children: conversation.timestamp }), _jsxs("div", { className: "flex items-center gap-1", children: [conversation.unreadCount > 0 && (_jsx("span", { className: "inline-flex items-center justify-center w-5 h-5 text-xs font-medium text-white bg-red-500 rounded-full", children: conversation.unreadCount })), (() => {
160
- const statusIcon = getStatusIcon(conversation.status);
161
- if (!statusIcon)
162
- return null;
163
- return (_jsx("div", { className: `w-5 h-5 ${statusIcon.bgColor} rounded-full flex items-center justify-center`, children: _jsx(Icon, { icon: statusIcon.icon, size: 12, className: statusIcon.iconColor }) }));
164
- })()] })] })] }) })] })] }, conversation.id))), filteredConversations.length === 0 && (_jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-gray-500", children: [_jsx(Icon, { icon: "chat-square-b", size: 48, className: "text-gray-300 mb-4" }), _jsx("p", { className: "text-lg font-medium mb-2", children: "Kh\u00F4ng t\u00ECm th\u1EA5y cu\u1ED9c tr\u00F2 chuy\u1EC7n" }), _jsx("p", { className: "text-sm text-center", children: searchQuery
165
- ? "Thử tìm kiếm với từ khóa khác"
166
- : "Chưa có cuộc trò chuyện nào" })] }))] })] }));
123
+ : "bg-white"}`, children: [selectedThreadId === conversation.threadId && (_jsx("div", { className: "absolute left-0 top-0 bottom-0 w-1 bg-blue-500" })), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "relative flex-shrink-0", children: _jsx(Badge, { dot: conversation.isOnline, status: conversation.isOnline ? "success" : "default", offset: [-2, 36], children: _jsx(Avatar, { size: 48, src: conversation.avatar, alt: conversation.name }) }) }), _jsx("div", { className: "flex-1 min-w-0", children: _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-semibold text-gray-900 text-sm truncate", children: conversation.name }), _jsx("p", { className: "text-xs text-gray-500 truncate mt-0.5", children: conversation.lastMessage })] }), _jsxs("div", { className: "flex flex-col items-end gap-1 ml-2", children: [_jsx("span", { className: "text-xs text-gray-400", children: conversation.timestamp }), _jsx("div", { className: "flex items-center gap-1", children: conversation.unreadCount > 0 && (_jsx(Badge, { count: conversation.unreadCount })) })] })] }) })] })] }, conversation.id))), filteredConversations.length === 0 && (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsx(Empty, { image: _jsx(Icon, { icon: "chat-square-b", size: 48, className: "text-gray-300" }), description: _jsxs("div", { children: [_jsx("p", { className: "text-lg font-medium mb-2 text-gray-500", children: "Kh\u00F4ng t\u00ECm th\u1EA5y cu\u1ED9c tr\u00F2 chuy\u1EC7n" }), _jsx("p", { className: "text-sm text-gray-400", children: searchQuery
124
+ ? "Thử tìm kiếm với từ khóa khác"
125
+ : "Chưa có cuộc trò chuyện nào" })] }) }) }))] })] }));
167
126
  };
168
127
  export default DeskConversationList;
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,yBAAyB,CAAC;AASjC,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAyL3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,yBAAyB,CAAC;AAkBjC,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CA0O3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -1,4 +1,15 @@
1
1
  "use client";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
2
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
14
  import { SessionType, } from "@openim/wasm-client-sdk";
4
15
  import { useChatContext } from "../../context/ChatContext";
@@ -7,11 +18,14 @@ import { Avatar, Button, Input, Tooltip } from "antd";
7
18
  import { Icon } from "../icon";
8
19
  import { useCallback, useEffect, useRef, useState } from "react";
9
20
  import clsx from "clsx";
10
- import { useSendMessage } from "../../hooks/message/useSendMessage";
21
+ import { useSendMessage, } from "../../hooks/message/useSendMessage";
22
+ import InfiniteLoader from "react-window-infinite-loader";
23
+ import { VariableSizeList as List, } from "react-window";
24
+ import AutoSizer from "react-virtualized-auto-sizer";
11
25
  const MessageList = (props) => {
12
26
  var _a, _b;
13
27
  const { conversationId, conversationData, onClose } = props;
14
- const { messageList, refetch } = useMessage(conversationId);
28
+ const { messageList, groupMessages, refetch } = useMessage(conversationId);
15
29
  const scrollRef = useRef(null);
16
30
  const shouldScrollToBottomRef = useRef(true);
17
31
  const lastMessageCountRef = useRef((messageList === null || messageList === void 0 ? void 0 : messageList.length) || 0);
@@ -25,6 +39,7 @@ const MessageList = (props) => {
25
39
  : (conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID) || "",
26
40
  });
27
41
  const [textMessage, setTextMessage] = useState("");
42
+ const [composing, setComposing] = useState(false);
28
43
  const [showScrollToBottomButton, setShowScrollToBottomButton] = useState(false);
29
44
  const scrollToBottom = useCallback((force = false) => {
30
45
  if (scrollRef.current) {
@@ -51,20 +66,27 @@ const MessageList = (props) => {
51
66
  setShowScrollToBottomButton(distanceFromBottom > SCROLL_DOWN_THRESHOLD &&
52
67
  !shouldScrollToBottomRef.current);
53
68
  }, []);
54
- const onSendTextMessage = async () => {
69
+ const onSendTextMessage = useCallback(async () => {
55
70
  setTextMessage("");
56
- const res = await sendTextMessage(textMessage);
71
+ const lastMessage = messageList === null || messageList === void 0 ? void 0 : messageList[(messageList === null || messageList === void 0 ? void 0 : messageList.length) - 1];
72
+ const res = await sendTextMessage(textMessage, lastMessage);
57
73
  if (res) {
58
74
  refetch();
59
75
  }
60
- };
61
- const renderMessageItem = useCallback((message) => {
62
- var _a, _b, _c;
63
- const isMine = (message === null || message === void 0 ? void 0 : message.sendID) === (user === null || user === void 0 ? void 0 : user.userID);
64
- return (_jsx("div", { className: clsx("flex", isMine ? "justify-end" : "justify-start"), children: _jsxs("div", { className: "flex items-end gap-2", children: [!isMine && (_jsx(Avatar, { children: ((_b = (_a = message === null || message === void 0 ? void 0 : message.senderNickname) === null || _a === void 0 ? void 0 : _a.charAt) === null || _b === void 0 ? void 0 : _b.call(_a, 0)) || "A" })), _jsxs("div", { className: "flex flex-col items-start", children: [!isMine && (_jsx("span", { className: "text-xs text-gray-500 mb-1 px-3", children: message === null || message === void 0 ? void 0 : message.senderNickname })), _jsx("div", { className: clsx("px-3 py-2 sm:px-4 sm:py-2 rounded-2xl max-w-full break-words", isMine
65
- ? "bg-blue-500 text-white"
66
- : "bg-gray-100 text-gray-900"), children: _jsx("p", { className: "text-sm sm:text-base whitespace-pre-wrap", children: ((_c = message === null || message === void 0 ? void 0 : message.textElem) === null || _c === void 0 ? void 0 : _c.content) || "Tin nhắn không khả dụng" }) })] })] }) }, message === null || message === void 0 ? void 0 : message.clientMsgID));
67
- }, [user === null || user === void 0 ? void 0 : user.userID]);
76
+ }, [textMessage, sendTextMessage, refetch, messageList]);
77
+ const renderMessageItem = useCallback((listItemProps) => {
78
+ const { index } = listItemProps;
79
+ const groupMessage = groupMessages === null || groupMessages === void 0 ? void 0 : groupMessages[index];
80
+ const messagesInGroup = (groupMessage === null || groupMessage === void 0 ? void 0 : groupMessage.messages) || [];
81
+ return (_jsxs("div", { children: [_jsx("div", { children: groupMessage === null || groupMessage === void 0 ? void 0 : groupMessage.sendTime }), messagesInGroup === null || messagesInGroup === void 0 ? void 0 : messagesInGroup.map((message) => {
82
+ var _a, _b, _c;
83
+ const isMine = (message === null || message === void 0 ? void 0 : message.sendID) === (user === null || user === void 0 ? void 0 : user.userID);
84
+ return (_jsx("div", { className: clsx("flex", isMine ? "justify-end" : "justify-start"), children: _jsxs("div", { className: "flex items-end gap-2", children: [!isMine && (_jsx(Avatar, { children: ((_b = (_a = message === null || message === void 0 ? void 0 : message.senderNickname) === null || _a === void 0 ? void 0 : _a.charAt) === null || _b === void 0 ? void 0 : _b.call(_a, 0)) || "A" })), _jsxs("div", { className: "flex flex-col items-start", children: [!isMine && (_jsx("span", { className: "text-xs text-gray-500 mb-1 px-3", children: message === null || message === void 0 ? void 0 : message.senderNickname })), _jsx("div", { className: clsx("px-3 py-2 sm:px-4 sm:py-2 rounded-2xl max-w-full break-words", isMine
85
+ ? "bg-blue-500 text-white"
86
+ : "bg-gray-100 text-gray-900"), children: _jsx("p", { className: "text-sm sm:text-base whitespace-pre-wrap", children: ((_c = message === null || message === void 0 ? void 0 : message.textElem) === null || _c === void 0 ? void 0 : _c.content) ||
87
+ "Tin nhắn không khả dụng" }) })] })] }) }, message === null || message === void 0 ? void 0 : message.clientMsgID));
88
+ })] }));
89
+ }, [user === null || user === void 0 ? void 0 : user.userID, groupMessages]);
68
90
  useEffect(() => {
69
91
  const currentMessageCount = (messageList === null || messageList === void 0 ? void 0 : messageList.length) || 0;
70
92
  const previousMessageCount = lastMessageCountRef.current;
@@ -82,10 +104,20 @@ const MessageList = (props) => {
82
104
  }
83
105
  lastMessageCountRef.current = currentMessageCount;
84
106
  }, [messageList, user === null || user === void 0 ? void 0 : user.userID, scrollToBottom]);
85
- return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full bg-white", children: [_jsxs("div", { className: "px-4 py-3 flex items-center border-b gap-3", children: [_jsx(Avatar, { src: conversationData === null || conversationData === void 0 ? void 0 : conversationData.faceURL, children: ((_b = (_a = conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName) === null || _a === void 0 ? void 0 : _a.charAt) === null || _b === void 0 ? void 0 : _b.call(_a, 0)) || "A" }), _jsxs("div", { className: "flex flex-col flex-1", children: [_jsx("p", { children: (conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName) || "" }), _jsx("p", { className: "text-xs text-gray-500", children: "2 thành viên" })] }), _jsx(Button, { type: "text", shape: "circle", icon: _jsx(Icon, { icon: "align-justify-o", size: 24 }) }), !!onClose && (_jsx(Button, { type: "text", shape: "circle", icon: _jsx(Icon, { icon: "close-b", size: 24 }), onClick: onClose }))] }), _jsx("div", { className: "flex flex-col flex-1 min-h-0", children: _jsx("div", { className: "relative h-full h-full", children: _jsx("div", { ref: scrollRef, className: "h-full overflow-y-auto p-3 sm:p-4 flex flex-col gap-2", children: messageList === null || messageList === void 0 ? void 0 : messageList.map((message) => renderMessageItem(message)) }) }) }), _jsx("div", { className: "border-t px-4 py-3", children: _jsx("div", { className: "border rounded-lg bg-gray-50", children: _jsxs("div", { className: "px-4 py-3 flex items-center gap-4", children: [_jsx(Input, { placeholder: "Nh\u1EADp tin nh\u1EAFn", size: "small", variant: "borderless", value: textMessage, onChange: (e) => setTextMessage(e.target.value), onKeyDown: (e) => {
107
+ return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full bg-white", children: [_jsxs("div", { className: "px-4 py-3 flex items-center border-b gap-3", children: [_jsx(Avatar, { src: conversationData === null || conversationData === void 0 ? void 0 : conversationData.faceURL, children: ((_b = (_a = conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName) === null || _a === void 0 ? void 0 : _a.charAt) === null || _b === void 0 ? void 0 : _b.call(_a, 0)) || "A" }), _jsxs("div", { className: "flex flex-col flex-1", children: [_jsx("p", { children: (conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName) || "" }), _jsx("p", { className: "text-xs text-gray-500", children: "2 thành viên" })] }), _jsx(Button, { type: "text", shape: "circle", icon: _jsx(Icon, { icon: "align-justify-o", size: 24 }) }), !!onClose && (_jsx(Button, { type: "text", shape: "circle", icon: _jsx(Icon, { icon: "close-b", size: 24 }), onClick: onClose }))] }), _jsx("div", { className: "flex flex-col flex-1 min-h-0", children: _jsx("div", { className: "relative h-full", children: _jsx(AutoSizer, { children: ({ height, width }) => (_jsx(InfiniteLoader, { isItemLoaded: () => true, loadMoreItems: () => { }, itemCount: (groupMessages === null || groupMessages === void 0 ? void 0 : groupMessages.length) || 0, children: (_a) => {
108
+ var { onItemsRendered, ref } = _a, rest = __rest(_a, ["onItemsRendered", "ref"]);
109
+ return (_jsx(List, Object.assign({ ref: ref }, rest, { itemCount: (groupMessages === null || groupMessages === void 0 ? void 0 : groupMessages.length) || 0, onItemsRendered: onItemsRendered, height: height, width: width, itemSize: (index) => {
110
+ const groupMessage = groupMessages === null || groupMessages === void 0 ? void 0 : groupMessages[index];
111
+ const messagesInGroup = (groupMessage === null || groupMessage === void 0 ? void 0 : groupMessage.messages) || [];
112
+ return (messagesInGroup === null || messagesInGroup === void 0 ? void 0 : messagesInGroup.length) * 50;
113
+ }, children: renderMessageItem })));
114
+ } })) }) }) }), _jsx("div", { className: "border-t px-4 py-3", children: _jsx("div", { className: "border rounded-lg bg-gray-50", children: _jsxs("div", { className: "px-4 py-3 flex items-center gap-4", children: [_jsx(Input, { placeholder: "Nh\u1EADp tin nh\u1EAFn", size: "small", variant: "borderless", value: textMessage, onChange: (e) => setTextMessage(e.target.value), onKeyDown: (e) => {
115
+ if (composing) {
116
+ return;
117
+ }
86
118
  if (e.key === "Enter") {
87
119
  onSendTextMessage();
88
120
  }
89
- } }), _jsx(Tooltip, { title: "G\u1EEDi tin nh\u1EAFn", children: _jsx(Button, { type: "primary", shape: "circle", size: "middle", icon: _jsx(Icon, { icon: "send-b", color: "white", size: 16 }), disabled: textMessage.length === 0, onClick: onSendTextMessage }) })] }) }) })] }));
121
+ }, onCompositionStart: () => setComposing(true), onCompositionEnd: () => setComposing(false) }), _jsx(Tooltip, { title: "G\u1EEDi tin nh\u1EAFn", children: _jsx(Button, { type: "primary", shape: "circle", size: "middle", icon: _jsx(Icon, { icon: "send-b", color: "white", size: 16 }), disabled: textMessage.length === 0, onClick: onSendTextMessage }) })] }) }) })] }));
90
122
  };
91
123
  export default MessageList;
@@ -0,0 +1,2 @@
1
+ export declare const coreWasmPath = "https://droppiistg.blob.core.windows.net/droppii-stg-public/3315964d-11d5-4d27-8af7-d2ec2354994f.wasm";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,0GACgF,CAAC"}
@@ -0,0 +1 @@
1
+ export const coreWasmPath = "https://droppiistg.blob.core.windows.net/droppii-stg-public/3315964d-11d5-4d27-8af7-d2ec2354994f.wasm";
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/constants/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEjD,eAAO,MAAM,QAAQ,EAAE,UAAU,CAAC,OAAO,MAAM,CAI7C,CAAC"}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/constants/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAGjD,eAAO,MAAM,QAAQ,EAAE,UAAU,CAAC,OAAO,MAAM,CAI7C,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import { getSDK } from "@openim/wasm-client-sdk";
2
+ import { coreWasmPath } from "./index";
2
3
  export const DChatSDK = getSDK({
3
- coreWasmPath: "https://pub-b11e10131a914403b2a326ec38f7e99f.r2.dev/openIM.wasm",
4
+ coreWasmPath,
4
5
  sqlWasmPath: "/sql-wasm.wasm",
6
+ debug: process.env.NODE_ENV === "development",
5
7
  });
@@ -1,5 +1,5 @@
1
1
  import { ChatContextType, ChatProviderProps } from "../types/chat";
2
2
  export declare const ChatContext: import("react").Context<ChatContextType>;
3
3
  export declare const useChatContext: () => ChatContextType;
4
- export declare const ChatProvider: ({ children, config }: ChatProviderProps) => import("react/jsx-runtime").JSX.Element;
4
+ export declare const ChatProvider: ({ children, config, refetchToken, }: ChatProviderProps) => import("react/jsx-runtime").JSX.Element;
5
5
  //# sourceMappingURL=ChatContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatContext.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAInE,eAAO,MAAM,WAAW,0CAEtB,CAAC;AAEH,eAAO,MAAM,cAAc,uBAAgC,CAAC;AAE5D,eAAO,MAAM,YAAY,GAAI,sBAAsB,iBAAiB,4CAkCnE,CAAC"}
1
+ {"version":3,"file":"ChatContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatContext.tsx"],"names":[],"mappings":"AAIA,OAAO,EACL,eAAe,EACf,iBAAiB,EAElB,MAAM,eAAe,CAAC;AAGvB,eAAO,MAAM,WAAW,0CAGtB,CAAC;AAEH,eAAO,MAAM,cAAc,uBAAgC,CAAC;AAE5D,eAAO,MAAM,YAAY,GAAI,qCAI1B,iBAAiB,4CAyEnB,CAAC"}
@@ -1,14 +1,16 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { createContext, useContext, useEffect, useState } from "react";
4
- import { Spin } from "antd";
4
+ import { CbEvents } from "@openim/wasm-client-sdk";
5
+ import { ConnectStatus, } from "../types/chat";
5
6
  import { DChatSDK } from "../constants/sdk";
6
7
  export const ChatContext = createContext({
7
8
  user: null,
9
+ connectStatus: ConnectStatus.Disconnected,
8
10
  });
9
11
  export const useChatContext = () => useContext(ChatContext);
10
- export const ChatProvider = ({ children, config }) => {
11
- const [loading, setLoading] = useState(true);
12
+ export const ChatProvider = ({ children, config, refetchToken, }) => {
13
+ const [connectStatus, setConnectStatus] = useState(ConnectStatus.Disconnected);
12
14
  const [user, setUser] = useState(null);
13
15
  const getUserInfo = () => {
14
16
  DChatSDK.getSelfUserInfo()
@@ -19,11 +21,10 @@ export const ChatProvider = ({ children, config }) => {
19
21
  console.log("getSelfUserInfo", errCode, errMsg);
20
22
  });
21
23
  };
22
- const handleLogin = () => {
23
- DChatSDK.login(config)
24
+ const handleLogin = (newToken) => {
25
+ DChatSDK.login(Object.assign(Object.assign({}, config), { token: newToken || config.token }))
24
26
  .then((res) => {
25
27
  getUserInfo();
26
- setLoading(false);
27
28
  })
28
29
  .catch(({ errCode, errMsg }) => {
29
30
  console.log("handleLogin", errCode, errMsg);
@@ -32,5 +33,39 @@ export const ChatProvider = ({ children, config }) => {
32
33
  useEffect(() => {
33
34
  handleLogin();
34
35
  }, [config]);
35
- return (_jsx(ChatContext.Provider, { value: { user }, children: loading ? _jsx(Spin, { fullscreen: true }) : children }));
36
+ useEffect(() => {
37
+ DChatSDK.on(CbEvents.OnUserTokenExpired, () => {
38
+ console.log("OnUserTokenExpired");
39
+ refetchToken().then((token) => {
40
+ if (!!token) {
41
+ handleLogin(token);
42
+ }
43
+ });
44
+ });
45
+ DChatSDK.on(CbEvents.OnUserTokenInvalid, () => {
46
+ console.log("OnUserTokenInvalid");
47
+ refetchToken().then((token) => {
48
+ if (!!token) {
49
+ handleLogin(token);
50
+ }
51
+ });
52
+ });
53
+ DChatSDK.on(CbEvents.OnConnectSuccess, () => {
54
+ setConnectStatus(ConnectStatus.Connected);
55
+ });
56
+ DChatSDK.on(CbEvents.OnConnecting, () => {
57
+ setConnectStatus(ConnectStatus.Connecting);
58
+ });
59
+ DChatSDK.on(CbEvents.OnConnectFailed, () => {
60
+ setConnectStatus(ConnectStatus.Disconnected);
61
+ });
62
+ return () => {
63
+ DChatSDK.off(CbEvents.OnUserTokenExpired, () => { });
64
+ DChatSDK.off(CbEvents.OnUserTokenInvalid, () => { });
65
+ DChatSDK.off(CbEvents.OnConnectSuccess, () => { });
66
+ DChatSDK.off(CbEvents.OnConnectFailed, () => { });
67
+ DChatSDK.off(CbEvents.OnConnecting, () => { });
68
+ };
69
+ }, [refetchToken]);
70
+ return (_jsx(ChatContext.Provider, { value: { user, connectStatus }, children: children }));
36
71
  };
@@ -1,6 +1,7 @@
1
1
  import { ConversationItem, SessionType } from "@openim/wasm-client-sdk";
2
- export declare const useConversationList: () => {
2
+ export declare const useConversationList: (selectedThreadId?: string) => {
3
3
  conversationList: ConversationItem[];
4
+ getAllConversationList: () => Promise<void>;
4
5
  };
5
6
  export declare const useConversationDetail: ({ sourceID, sessionType, }: {
6
7
  sourceID: string;
@@ -1 +1 @@
1
- {"version":3,"file":"useConversation.d.ts","sourceRoot":"","sources":["../../../src/hooks/conversation/useConversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIxE,eAAO,MAAM,mBAAmB;;CAoC/B,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,4BAGnC;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;CAC1B;;CAwBA,CAAC"}
1
+ {"version":3,"file":"useConversation.d.ts","sourceRoot":"","sources":["../../../src/hooks/conversation/useConversation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,WAAW,EAEZ,MAAM,yBAAyB,CAAC;AAIjC,eAAO,MAAM,mBAAmB,GAAI,mBAAmB,MAAM;;;CA0C5D,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,4BAGnC;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;CAC1B;;CAuBA,CAAC"}
@@ -1,35 +1,38 @@
1
+ import { CbEvents, } from "@openim/wasm-client-sdk";
1
2
  import { useCallback, useEffect, useState } from "react";
2
3
  import { DChatSDK } from "../../constants/sdk";
3
- export const useConversationList = () => {
4
+ export const useConversationList = (selectedThreadId) => {
4
5
  const [conversationList, setConversationList] = useState([]);
5
6
  const getAllConversationList = useCallback(async () => {
6
7
  DChatSDK.getAllConversationList()
7
8
  .then(({ data }) => {
8
- console.log("getAllConversationList", data);
9
9
  setConversationList(data);
10
10
  })
11
11
  .catch((err) => {
12
12
  console.log("getAllConversationList", err);
13
13
  });
14
14
  }, []);
15
- const getOneConversation = useCallback(async () => {
16
- DChatSDK.getOneConversation({
17
- sourceID: "3408237279",
18
- sessionType: 3,
19
- })
20
- .then(({ data }) => {
21
- console.log("getOneConversation", data);
22
- })
23
- .catch((err) => {
24
- console.log("getOneConversation", err);
25
- });
26
- }, []);
27
15
  useEffect(() => {
28
16
  getAllConversationList();
29
- getOneConversation();
30
17
  }, [getAllConversationList]);
18
+ useEffect(() => {
19
+ DChatSDK.on(CbEvents.OnConversationChanged, ({ data }) => {
20
+ setConversationList(data);
21
+ });
22
+ return () => {
23
+ DChatSDK.off(CbEvents.OnConversationChanged, () => { });
24
+ };
25
+ }, []);
26
+ useEffect(() => {
27
+ if (selectedThreadId) {
28
+ DChatSDK.markConversationMessageAsRead(selectedThreadId).catch(({ errCode, errMsg }) => {
29
+ console.error("Failed to mark messages as read", errCode, errMsg);
30
+ });
31
+ }
32
+ }, [selectedThreadId]);
31
33
  return {
32
34
  conversationList,
35
+ getAllConversationList,
33
36
  };
34
37
  };
35
38
  export const useConversationDetail = ({ sourceID, sessionType, }) => {
@@ -40,7 +43,6 @@ export const useConversationDetail = ({ sourceID, sessionType, }) => {
40
43
  sessionType,
41
44
  })
42
45
  .then(({ data }) => {
43
- console.log("getOneConversation", data);
44
46
  setConversationDetail(data);
45
47
  })
46
48
  .catch((err) => {
@@ -1,6 +1,9 @@
1
1
  import { MessageItem } from "@openim/wasm-client-sdk";
2
+ import { GroupMessageItem } from "../../types/chat";
2
3
  export declare const useMessage: (conversationId?: string) => {
4
+ groupMessages: GroupMessageItem[];
3
5
  refetch: () => void;
6
+ markConversationMessageAsRead: (message?: MessageItem) => void;
4
7
  isEnd?: boolean | undefined;
5
8
  errCode?: number | undefined;
6
9
  errMsg?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"useMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,WAAW,EACZ,MAAM,yBAAyB,CAAC;AAGjC,eAAO,MAAM,UAAU,GAAI,iBAAiB,MAAM;;;;;;CAqDjD,CAAC"}
1
+ {"version":3,"file":"useMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,WAAW,EACZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAqB,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,eAAO,MAAM,UAAU,GAAI,iBAAiB,MAAM;;;8CAgEnC,WAAW;;;;;CA8BzB,CAAC"}
@@ -1,8 +1,33 @@
1
- import { useCallback, useEffect, useState } from "react";
1
+ import { useCallback, useEffect, useMemo, useState } from "react";
2
2
  import { ViewType, CbEvents, } from "@openim/wasm-client-sdk";
3
3
  import { DChatSDK } from "../../constants/sdk";
4
4
  export const useMessage = (conversationId) => {
5
5
  const [dataMessages, setDataMessages] = useState(null);
6
+ const groupMessages = useMemo(() => {
7
+ var _a;
8
+ if (!dataMessages || !(dataMessages === null || dataMessages === void 0 ? void 0 : dataMessages.messageList))
9
+ return [];
10
+ const mGroupMessages = (_a = dataMessages === null || dataMessages === void 0 ? void 0 : dataMessages.messageList) === null || _a === void 0 ? void 0 : _a.reduce((acc, cur) => {
11
+ const extendMessageInfo = JSON.parse((cur === null || cur === void 0 ? void 0 : cur.ex) || "{}");
12
+ if (extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.groupMessageID) {
13
+ const findGroupMessageIndex = acc.findIndex((item) => item.groupMessageID === (extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.groupMessageID));
14
+ if (findGroupMessageIndex === -1) {
15
+ acc.push({
16
+ groupMessageID: extendMessageInfo.groupMessageID,
17
+ messages: [cur],
18
+ sendID: cur.sendID,
19
+ sendTime: cur.sendTime,
20
+ });
21
+ }
22
+ else {
23
+ acc[findGroupMessageIndex].messages.push(cur);
24
+ }
25
+ }
26
+ return acc;
27
+ }, []);
28
+ return mGroupMessages;
29
+ }, [dataMessages]);
30
+ console.log("groupMessages", groupMessages);
6
31
  const getAdvancedHistoryMessageList = useCallback(() => {
7
32
  if (!conversationId)
8
33
  return;
@@ -20,7 +45,6 @@ export const useMessage = (conversationId) => {
20
45
  viewType: ViewType.History,
21
46
  })
22
47
  .then(({ data }) => {
23
- console.log("getAdvancedHistoryMessageList", data);
24
48
  setDataMessages(data);
25
49
  })
26
50
  .catch((err) => {
@@ -30,17 +54,25 @@ export const useMessage = (conversationId) => {
30
54
  const onRecvNewMessages = useCallback((data) => {
31
55
  getAdvancedHistoryMessageList();
32
56
  }, [getAdvancedHistoryMessageList]);
57
+ const markConversationMessageAsRead = useCallback((message) => {
58
+ if (!conversationId)
59
+ return;
60
+ DChatSDK.markConversationMessageAsRead(conversationId)
61
+ .then()
62
+ .catch(({ errCode, errMsg }) => {
63
+ // Failed call
64
+ });
65
+ }, [conversationId]);
33
66
  useEffect(() => {
34
67
  getAdvancedHistoryMessageList();
35
68
  }, [getAdvancedHistoryMessageList]);
36
69
  useEffect(() => {
37
70
  DChatSDK.on(CbEvents.OnRecvNewMessages, ({ data }) => {
38
- console.log("OnRecvNewMessages123", data);
39
71
  onRecvNewMessages(data);
40
72
  });
41
73
  return () => {
42
74
  DChatSDK.off(CbEvents.OnRecvNewMessages, () => { });
43
75
  };
44
76
  }, [onRecvNewMessages]);
45
- return Object.assign(Object.assign({}, dataMessages), { refetch: getAdvancedHistoryMessageList });
77
+ return Object.assign(Object.assign({}, dataMessages), { groupMessages, refetch: getAdvancedHistoryMessageList, markConversationMessageAsRead });
46
78
  };
@@ -1,10 +1,13 @@
1
+ import { MessageItem } from "@openim/wasm-client-sdk";
2
+ import { ExtendMessageInfo } from "../../types/chat";
1
3
  interface SendMessageProps {
2
4
  recvID: string;
3
5
  groupID: string;
4
6
  }
5
- export declare const createTextMessage: (text: string) => Promise<import("@openim/wasm-client-sdk").MessageItem | null>;
7
+ export declare const createTextMessage: (text: string) => Promise<MessageItem | null>;
6
8
  export declare const useSendMessage: (props: SendMessageProps) => {
7
- sendTextMessage: (text: string) => Promise<boolean>;
9
+ sendTextMessage: (text: string, lastMessage?: MessageItem) => Promise<boolean>;
8
10
  };
11
+ export declare const generateExtendMessageInfo: (currentUserID: string, lastMessage?: MessageItem) => ExtendMessageInfo;
9
12
  export {};
10
13
  //# sourceMappingURL=useSendMessage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSendMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useSendMessage.ts"],"names":[],"mappings":"AAGA,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,iBAAiB,GAAU,MAAM,MAAM,kEAUnD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,gBAAgB;4BAIf,MAAM;CAsB5C,CAAC"}
1
+ {"version":3,"file":"useSendMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useSendMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,iBAAiB,GAAU,MAAM,MAAM,gCAanD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,gBAAgB;4BAKrC,MAAM,gBAAgB,WAAW;CAiCjD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,eAAe,MAAM,EACrB,cAAc,WAAW,KAapB,iBACN,CAAC"}
@@ -1,41 +1,54 @@
1
1
  import { DChatSDK } from "../../constants/sdk";
2
+ import dayjs from "dayjs";
3
+ import { v4 as uuidv4 } from "uuid";
2
4
  import { useChatContext } from "../../context/ChatContext";
5
+ import { useCallback } from "react";
3
6
  export const createTextMessage = async (text) => {
4
- let textMessage = await DChatSDK.createTextMessage(text)
7
+ let textMessage = await DChatSDK.createTextMessage(text, new Date().getTime().toString())
5
8
  .then(({ data }) => {
6
9
  return data;
7
10
  })
8
11
  .catch(({ errCode, errMsg }) => {
9
- console.log("createTextMessage", errCode, errMsg);
12
+ console.error("createTextMessage", errCode, errMsg);
10
13
  return null;
11
14
  });
12
15
  return textMessage;
13
16
  };
14
17
  export const useSendMessage = (props) => {
15
- const { user } = useChatContext();
16
18
  const { recvID, groupID } = props;
17
- const sendTextMessage = async (text) => {
19
+ const { user } = useChatContext();
20
+ const sendTextMessage = useCallback(async (text, lastMessage) => {
18
21
  let result = false;
19
22
  if (!recvID && !groupID)
20
23
  return false;
21
24
  const textMessage = await createTextMessage(text);
22
- console.log("textMessage", textMessage);
23
25
  if (!textMessage)
24
26
  return false;
27
+ const extendMessageInfo = generateExtendMessageInfo((user === null || user === void 0 ? void 0 : user.userID) || "", lastMessage);
25
28
  try {
26
29
  await DChatSDK.sendMessage({
27
30
  recvID,
28
31
  groupID,
29
- message: textMessage,
30
- });
32
+ message: Object.assign(Object.assign({}, textMessage), { ex: JSON.stringify(extendMessageInfo) || "{}" }),
33
+ }, new Date().getTime().toString());
31
34
  result = true;
32
35
  }
33
36
  catch (error) {
34
37
  console.log("sendMessage", error);
35
38
  }
36
39
  return result;
37
- };
40
+ }, [recvID, groupID, user]);
38
41
  return {
39
42
  sendTextMessage,
40
43
  };
41
44
  };
45
+ export const generateExtendMessageInfo = (currentUserID, lastMessage) => {
46
+ const diffSendTime = dayjs().diff(lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.sendTime, "minutes");
47
+ const isSameSender = (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.sendID) === currentUserID;
48
+ const lastMessageExtendMessageInfo = JSON.parse((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.ex) || "{}");
49
+ return {
50
+ groupMessageID: isSameSender && diffSendTime <= 5
51
+ ? (lastMessageExtendMessageInfo === null || lastMessageExtendMessageInfo === void 0 ? void 0 : lastMessageExtendMessageInfo.groupMessageID) || uuidv4()
52
+ : uuidv4(),
53
+ };
54
+ };
@@ -0,0 +1,9 @@
1
+ interface MessageStore {
2
+ selectedThreadId: string;
3
+ selectedSourceId: string;
4
+ setSelectedThreadId: (threadId: string) => void;
5
+ setSelectedSourceId: (sourceId: string) => void;
6
+ }
7
+ declare const useMessageStore: import("zustand").UseBoundStore<import("zustand").StoreApi<MessageStore>>;
8
+ export default useMessageStore;
9
+ //# sourceMappingURL=useMessageStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMessageStore.d.ts","sourceRoot":"","sources":["../../../src/hooks/zustand/useMessageStore.ts"],"names":[],"mappings":"AAEA,UAAU,YAAY;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAED,QAAA,MAAM,eAAe,2EAKlB,CAAC;AAEJ,eAAe,eAAe,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { create } from "zustand";
2
+ const useMessageStore = create((set) => ({
3
+ selectedThreadId: "",
4
+ setSelectedThreadId: (threadId) => set({ selectedThreadId: threadId }),
5
+ selectedSourceId: "",
6
+ setSelectedSourceId: (sourceId) => set({ selectedSourceId: sourceId }),
7
+ }));
8
+ export default useMessageStore;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import DChatDeskMessage from "./screens/desk-message";
1
+ import DChatDeskMessage from "./screens/deskMessage";
2
+ import DChatBubble from "./screens/chatBubble";
2
3
  import { Platform, LogLevel, SessionType, InitAndLoginConfig } from "@openim/wasm-client-sdk";
3
4
  import { Icon } from "./components/icon";
4
- import ChatBubble from "./components/ChatBubble";
5
5
  export { ChatProvider, useChatContext } from "./context/ChatContext";
6
- export { DChatDeskMessage, ChatBubble, Icon };
6
+ export { DChatDeskMessage, DChatBubble, Icon };
7
7
  export { useDChatAuth } from "./hooks/user/useAuth";
8
8
  export { Platform as DChatPlatform, LogLevel as DChatLogLevel, SessionType as DChatSessionType, };
9
9
  export type { InitAndLoginConfig as DChatInitAndLoginConfig };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,wBAAwB,CAAC;AACtD,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,UAAU,MAAM,yBAAyB,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAG9C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIpD,OAAO,EACL,QAAQ,IAAI,aAAa,EACzB,QAAQ,IAAI,aAAa,EACzB,WAAW,IAAI,gBAAgB,GAChC,CAAC;AAEF,YAAY,EAAE,kBAAkB,IAAI,uBAAuB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,uBAAuB,CAAC;AACrD,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIpD,OAAO,EACL,QAAQ,IAAI,aAAa,EACzB,QAAQ,IAAI,aAAa,EACzB,WAAW,IAAI,gBAAgB,GAChC,CAAC;AAEF,YAAY,EAAE,kBAAkB,IAAI,uBAAuB,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import DChatDeskMessage from "./screens/desk-message";
1
+ import DChatDeskMessage from "./screens/deskMessage";
2
+ import DChatBubble from "./screens/chatBubble";
2
3
  import { Platform, LogLevel, SessionType, } from "@openim/wasm-client-sdk";
3
4
  import { Icon } from "./components/icon";
4
- import ChatBubble from "./components/ChatBubble";
5
5
  // Main exports for the SDK
6
6
  export { ChatProvider, useChatContext } from "./context/ChatContext";
7
7
  //Components
8
- export { DChatDeskMessage, ChatBubble, Icon };
8
+ export { DChatDeskMessage, DChatBubble, Icon };
9
9
  //Hooks
10
10
  export { useDChatAuth } from "./hooks/user/useAuth";
11
11
  // export * from "./types/sdk";
@@ -0,0 +1,10 @@
1
+ import { SessionType } from "@openim/wasm-client-sdk";
2
+ interface DChatBubbleProps {
3
+ conversationId: string;
4
+ sourceID: string;
5
+ sessionType: SessionType;
6
+ className?: string;
7
+ }
8
+ declare const DChatBubble: (props: DChatBubbleProps) => import("react/jsx-runtime").JSX.Element | null;
9
+ export default DChatBubble;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/chatBubble/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAKtD,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,mDAY3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import ChatBubble from "../../components/chatBubble/ChatBubble";
3
+ import { useChatContext } from "../../context/ChatContext";
4
+ import { ConnectStatus } from "../../types/chat";
5
+ const DChatBubble = (props) => {
6
+ const { conversationId, sourceID, sessionType, className } = props;
7
+ const { connectStatus } = useChatContext();
8
+ if (connectStatus !== ConnectStatus.Connected)
9
+ return null;
10
+ return (_jsx(ChatBubble, { conversationId: conversationId, sourceID: sourceID, sessionType: sessionType, className: className }));
11
+ };
12
+ export default DChatBubble;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/deskMessage/index.tsx"],"names":[],"mappings":"AAYA,QAAA,MAAM,gBAAgB,+CA4BrB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { SessionType } from "@openim/wasm-client-sdk";
4
+ import MessageList from "../../components/message/MessageList";
5
+ import DeskConversationList from "../../components/conversation/DeskConversationList";
6
+ import { useConversationDetail } from "../../hooks/conversation/useConversation";
7
+ import AssignedSessionFilter from "../../components/session/AssignedSessionFilter";
8
+ import useMessageStore from "../../hooks/zustand/useMessageStore";
9
+ import { useChatContext } from "../../context/ChatContext";
10
+ import { Spin } from "antd";
11
+ import { ConnectStatus } from "../../types/chat";
12
+ const DChatDeskMessage = () => {
13
+ const selectedThreadId = useMessageStore((state) => state.selectedThreadId);
14
+ const selectedSourceId = useMessageStore((state) => state.selectedSourceId);
15
+ const { conversationDetail } = useConversationDetail({
16
+ sourceID: selectedSourceId,
17
+ sessionType: SessionType.Group,
18
+ });
19
+ const { connectStatus } = useChatContext();
20
+ return (_jsx(_Fragment, { children: connectStatus === ConnectStatus.Connected ? (_jsxs("div", { className: "flex flex-1 flex-row h-screen bg-gray-50", children: [_jsx(AssignedSessionFilter, {}), _jsx(DeskConversationList, {}), _jsx(MessageList, { conversationId: selectedThreadId, conversationData: conversationDetail })] })) : (_jsx("div", { className: "flex flex-1 flex-row h-screen bg-gray-50", children: connectStatus === ConnectStatus.Connecting && _jsx(Spin, { fullscreen: true }) })) }));
21
+ };
22
+ export default DChatDeskMessage;
@@ -1 +1 @@
1
- *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.absolute{position:absolute}.relative{position:relative}.-bottom-0\.5{bottom:-.125rem}.-right-0\.5{right:-.125rem}.bottom-0{bottom:0}.left-0{left:0}.left-3{left:.75rem}.top-0{top:0}.top-1\/2{top:50%}.\!z-\[9999\]{z-index:9999!important}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.mt-0\.5{margin-top:.125rem}.flex{display:flex}.inline-flex{display:inline-flex}.h-12{height:3rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-full{height:100%}.h-screen{height:100vh}.min-h-0{min-height:0}.w-1{width:.25rem}.w-12{width:3rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-64{width:16rem}.w-full{width:100%}.min-w-0{min-width:0}.max-w-full{max-width:100%}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-r-2{border-right-width:2px}.border-t{border-top-width:1px}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity,1))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity,1))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-orange-100{--tw-bg-opacity:1;background-color:rgb(255 237 213/var(--tw-bg-opacity,1))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity,1))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-3{padding:.75rem}.p-4{padding:1rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pr-4{padding-right:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-500{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hover\:bg-gray-50:hover{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}@media (min-width:640px){.sm\:p-4{padding:1rem}.sm\:px-4{padding-left:1rem;padding-right:1rem}.sm\:py-2{padding-top:.5rem;padding-bottom:.5rem}.sm\:text-base{font-size:1rem;line-height:1.5rem}}
1
+ *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.absolute{position:absolute}.relative{position:relative}.bottom-0{bottom:0}.left-0{left:0}.top-0{top:0}.\!z-\[9999\]{z-index:9999!important}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.mt-0\.5{margin-top:.125rem}.flex{display:flex}.h-full{height:100%}.h-screen{height:100vh}.min-h-0{min-height:0}.w-1{width:.25rem}.w-64{width:16rem}.w-full{width:100%}.min-w-0{min-width:0}.max-w-full{max-width:100%}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.cursor-pointer{cursor:pointer}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded-2xl{border-radius:1rem}.rounded-lg{border-radius:.5rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-r-2{border-right-width:2px}.border-t{border-top-width:1px}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity,1))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.p-3{padding:.75rem}.p-4{padding:1rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.text-left{text-align:left}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-500{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hover\:bg-gray-50:hover{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}@media (min-width:640px){.sm\:px-4{padding-left:1rem;padding-right:1rem}.sm\:py-2{padding-top:.5rem;padding-bottom:.5rem}.sm\:text-base{font-size:1rem;line-height:1.5rem}}
@@ -1,9 +1,23 @@
1
- import { InitAndLoginConfig, SelfUserInfo } from "@openim/wasm-client-sdk";
1
+ import { InitAndLoginConfig, MessageItem, SelfUserInfo } from "@openim/wasm-client-sdk";
2
+ export declare enum ConnectStatus {
3
+ Disconnected = 0,
4
+ Connected = 1,
5
+ Connecting = 2
6
+ }
2
7
  export interface ChatContextType {
3
8
  user: SelfUserInfo | null;
9
+ connectStatus: ConnectStatus;
4
10
  }
5
11
  export interface ChatProviderProps {
6
12
  children: React.ReactNode;
7
13
  config: InitAndLoginConfig;
14
+ refetchToken: () => Promise<string>;
15
+ }
16
+ export interface GroupMessageItem extends Pick<MessageItem, "sendID" | "sendTime"> {
17
+ groupMessageID: string;
18
+ messages: MessageItem[];
19
+ }
20
+ export interface ExtendMessageInfo {
21
+ groupMessageID: string;
8
22
  }
9
23
  //# sourceMappingURL=chat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/types/chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE3E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,kBAAkB,CAAC;CAC5B"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/types/chat.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,YAAY,EACb,MAAM,yBAAyB,CAAC;AAEjC,oBAAY,aAAa;IACvB,YAAY,IAAI;IAChB,SAAS,IAAI;IACb,UAAU,IAAI;CACf;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,gBACf,SAAQ,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,UAAU,CAAC;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;CACxB"}
@@ -1 +1,6 @@
1
- export {};
1
+ export var ConnectStatus;
2
+ (function (ConnectStatus) {
3
+ ConnectStatus[ConnectStatus["Disconnected"] = 0] = "Disconnected";
4
+ ConnectStatus[ConnectStatus["Connected"] = 1] = "Connected";
5
+ ConnectStatus[ConnectStatus["Connecting"] = 2] = "Connecting";
6
+ })(ConnectStatus || (ConnectStatus = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@droppii-org/chat-sdk",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "description": "Droppii React Chat SDK",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -64,13 +64,21 @@
64
64
  "dependencies": {
65
65
  "@openim/wasm-client-sdk": "3.8.3-patch.10",
66
66
  "@tailwindcss/postcss": "^4.1.12",
67
+ "@types/react-window": "^1.8.8",
68
+ "@types/react-window-infinite-loader": "^1.0.9",
67
69
  "antd": "^5.27.0",
68
70
  "clsx": "^2.0.0",
71
+ "dayjs": "^1.11.13",
69
72
  "lucide-react": "^0.263.1",
70
73
  "postcss": "^8.5.6",
71
74
  "react-icomoon": "^2.6.1",
75
+ "react-virtualized-auto-sizer": "^1.0.26",
76
+ "react-window": "^1.8.11",
77
+ "react-window-infinite-loader": "^1.0.10",
72
78
  "tailwind-merge": "^2.0.0",
73
- "tailwindcss": "^3.3.0"
79
+ "tailwindcss": "^3.3.0",
80
+ "uuid": "^11.1.0",
81
+ "zustand": "^5.0.7"
74
82
  },
75
83
  "peerDependencies": {
76
84
  "react": "^18.0.0",
Binary file
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChatBubble.d.ts","sourceRoot":"","sources":["../../src/components/ChatBubble.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,UAAU,eAAe;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,UAAU,GAAI,uDAKjB,eAAe,4CAmDjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/index.tsx"],"names":[],"mappings":"AAQA,QAAA,MAAM,gBAAgB,+CAcrB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -1,14 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { SessionType } from "@openim/wasm-client-sdk";
4
- import MessageList from "../../components/message/MessageList";
5
- import DeskConversationList from "../../components/conversation/DeskConversationList";
6
- import { useConversationDetail } from "../../hooks/conversation/useConversation";
7
- const DChatDeskMessage = () => {
8
- const { conversationDetail } = useConversationDetail({
9
- sourceID: "3408237279",
10
- sessionType: SessionType.Group,
11
- });
12
- return (_jsxs("div", { className: "flex flex-1 flex-row h-screen bg-gray-50", children: [_jsx(DeskConversationList, {}), _jsx(MessageList, { conversationId: "sg_3408237279", conversationData: conversationDetail })] }));
13
- };
14
- export default DChatDeskMessage;