@droppii-org/chat-sdk 0.4.11 → 0.4.12

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ConversationDetailInput.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationDetailInput.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAkB/D,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,QAAA,MAAM,uBAAuB,GAAI,4EAM9B,4BAA4B,4CAynB9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ConversationDetailInput.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationDetailInput.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAkB/D,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,QAAA,MAAM,uBAAuB,GAAI,4EAM9B,4BAA4B,4CA8qB9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -4,8 +4,10 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import { useTranslation } from "react-i18next";
5
5
  import { useBoolean } from "ahooks";
6
6
  import clsx from "clsx";
7
+ import { Button, message as toastMessage } from "antd";
7
8
  import { Icon } from "../../components/icon";
8
9
  import { useSendMessage } from "../../hooks/message/useSendMessage";
10
+ import { useJoinPublicGroup } from "../../hooks/group/useJoinPublicGroup";
9
11
  import useAuthStore from "../../store/auth";
10
12
  import useConversationStore from "../../store/conversation";
11
13
  import useMessageDraftStore from "../../store/messageDraft";
@@ -36,6 +38,38 @@ const ConversationDetailInput = ({ placeholder, onSendMessage, onInputChange, mo
36
38
  const conversationId = selectedConversationId || (conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID) || "";
37
39
  const isConversationReady = !!conversationData && (!!conversationData.userID || !!conversationData.groupID);
38
40
  const isViewOnlyMember = useConversationStore((state) => state.isViewOnlyMember);
41
+ const setIsViewOnlyMember = useConversationStore((state) => state.setIsViewOnlyMember);
42
+ const getCurrentMemberInGroupByReq = useConversationStore((state) => state.getCurrentMemberInGroupByReq);
43
+ const getSelfGroupPermissionByReq = useConversationStore((state) => state.getSelfGroupPermissionByReq);
44
+ const { mutate: joinPublicGroup, isPending: isJoiningPublicGroup } = useJoinPublicGroup();
45
+ const handleJoinPublicGroup = useCallback(() => {
46
+ const groupID = conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID;
47
+ if (!groupID)
48
+ return;
49
+ joinPublicGroup({ groupID }, {
50
+ onSuccess: async () => {
51
+ toastMessage.success(tCommon("join_group_success"));
52
+ // updateCurrentConversation's revalidation only runs on a
53
+ // conversationID change — this is the same conversation the user
54
+ // was already viewing, so refresh membership/permissions directly
55
+ // instead, and flip isViewOnlyMember off immediately rather than
56
+ // waiting on a WS event that may not fire right away.
57
+ setIsViewOnlyMember(false);
58
+ await Promise.allSettled([
59
+ getCurrentMemberInGroupByReq(groupID),
60
+ getSelfGroupPermissionByReq(groupID),
61
+ ]);
62
+ },
63
+ onError: () => toastMessage.error(tCommon("join_group_failed")),
64
+ });
65
+ }, [
66
+ conversationData,
67
+ getCurrentMemberInGroupByReq,
68
+ getSelfGroupPermissionByReq,
69
+ joinPublicGroup,
70
+ setIsViewOnlyMember,
71
+ tCommon,
72
+ ]);
39
73
  const sendMessageOptions = useMemo(() => ({
40
74
  scrollEvent: "CONVERSATION_CHAT_SCROLL_TO_BOTTOM_IF_AT_BOTTOM",
41
75
  }), []);
@@ -408,7 +442,7 @@ const ConversationDetailInput = ({ placeholder, onSendMessage, onInputChange, mo
408
442
  void handleSend();
409
443
  };
410
444
  if (isViewOnlyMember) {
411
- return (_jsx("div", { "data-testid": "conversation-detail-input-view-only", className: "flex w-full shrink-0 items-center justify-center bg-chat-bubble-neutral/[0.05] px-4 py-3 text-center text-sm text-gray-500", children: t("thread_detail.view_only_notice") }));
445
+ return (_jsxs("div", { "data-testid": "conversation-detail-input-view-only", className: "flex w-full shrink-0 items-center justify-between gap-3 bg-chat-bubble-neutral/[0.05] px-4 py-3", children: [_jsx("span", { className: "text-sm text-gray-500", children: t("thread_detail.view_only_notice") }), _jsx(Button, { type: "primary", size: "small", loading: isJoiningPublicGroup, onClick: handleJoinPublicGroup, children: tCommon("join_group") })] }));
412
446
  }
413
447
  return (_jsxs("div", { ref: containerRef, "data-testid": "conversation-detail-input", "data-cp-name": "ConversationDetailInput", className: "flex w-full shrink-0 flex-col bg-chat-bubble-neutral/[0.05]", children: [_jsx("input", { ref: mediaInputRef, type: "file", accept: "image/jpeg,image/png,image/jpg,video/*", multiple: true, className: "hidden", onChange: handleMediaInputChange }), _jsx("input", { ref: documentInputRef, type: "file", accept: ".pdf,.doc,.docx", multiple: true, className: "hidden", onChange: handleDocumentInputChange }), _jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && (_jsx(FilePreviewList, { files: listUploadFiles, onRemove: (file) => handleRemoveFile(file.uid), onVideoReady: () => setIsVideoLoading(false) })), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setPreviewDismissed(true) })), _jsxs("div", { className: "flex items-end gap-3 px-3 py-2", children: [_jsx("div", { className: "flex shrink-0 items-center", children: _jsx("button", { type: "button", onClick: handleToggleMoreOption, "aria-label": t("thread_detail.more_option.toggle"), "aria-expanded": isMoreOptionOpen, "data-testid": "conversation-detail-more-option-toggle", className: "flex py-3 items-center justify-center rounded-full", children: isMoreOptionOpen ? (_jsx(Icon, { icon: "close-circle-b", size: 24, className: "text-primary-400" })) : (_jsx(Icon, { icon: "plus-circle-o", size: 24, className: "text-gray-900" })) }) }), _jsx("div", { className: clsx("flex min-w-0 flex-1 overflow-hidden rounded-xl border bg-white transition-shadow", isFocused
414
448
  ? "border-primary-200 shadow-primary-focus"
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAGL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAc/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CA0UpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAGL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAc/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CAgYpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -10,7 +10,8 @@ import EnterHandler from "./EnterHandler";
10
10
  import ActionBar from "./ActionBar";
11
11
  import { AccountType, } from "../../../types/chat";
12
12
  import { useSendMessage } from "../../../hooks/message/useSendMessage";
13
- import { Modal, Popover } from "antd";
13
+ import { useJoinPublicGroup } from "../../../hooks/group/useJoinPublicGroup";
14
+ import { Button, Modal, Popover, message as toastMessage } from "antd";
14
15
  import FilePreview from "./FilePreview";
15
16
  import LinkInputPreview from "./LinkInputPreview";
16
17
  import ComposerTextSyncPlugin from "./ComposerTextSyncPlugin";
@@ -72,6 +73,38 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
72
73
  const quotedMessage = useConversationStore((state) => state.quotedMessage);
73
74
  const conversationData = useConversationStore((state) => state.conversationData);
74
75
  const isViewOnlyMember = useConversationStore((state) => state.isViewOnlyMember);
76
+ const setIsViewOnlyMember = useConversationStore((state) => state.setIsViewOnlyMember);
77
+ const getCurrentMemberInGroupByReq = useConversationStore((state) => state.getCurrentMemberInGroupByReq);
78
+ const getSelfGroupPermissionByReq = useConversationStore((state) => state.getSelfGroupPermissionByReq);
79
+ const { mutate: joinPublicGroup, isPending: isJoiningPublicGroup } = useJoinPublicGroup();
80
+ const handleJoinPublicGroup = useCallback(() => {
81
+ const groupID = conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID;
82
+ if (!groupID)
83
+ return;
84
+ joinPublicGroup({ groupID }, {
85
+ onSuccess: async () => {
86
+ toastMessage.success(t("join_group_success"));
87
+ // updateCurrentConversation's revalidation only runs on a
88
+ // conversationID change — this is the same conversation the user
89
+ // was already viewing, so refresh membership/permissions directly
90
+ // instead, and flip isViewOnlyMember off immediately rather than
91
+ // waiting on a WS event that may not fire right away.
92
+ setIsViewOnlyMember(false);
93
+ await Promise.allSettled([
94
+ getCurrentMemberInGroupByReq(groupID),
95
+ getSelfGroupPermissionByReq(groupID),
96
+ ]);
97
+ },
98
+ onError: () => toastMessage.error(t("join_group_failed")),
99
+ });
100
+ }, [
101
+ conversationData,
102
+ getCurrentMemberInGroupByReq,
103
+ getSelfGroupPermissionByReq,
104
+ joinPublicGroup,
105
+ setIsViewOnlyMember,
106
+ t,
107
+ ]);
75
108
  // Internal notes are a CX-support concept (team-only remarks not sent to
76
109
  // the customer) — meaningless inside a real member-managed group, where
77
110
  // everyone in the thread already is the "team".
@@ -216,7 +249,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
216
249
  closeCanned();
217
250
  };
218
251
  if (isViewOnlyMember) {
219
- return (_jsx("div", { "data-testid": "message-footer-view-only", className: "flex w-full items-center justify-center border-t border-gray-25 bg-white px-4 py-3 text-center text-sm text-gray-500", children: tConversationInbox("thread_detail.view_only_notice") }));
252
+ return (_jsxs("div", { "data-testid": "message-footer-view-only", className: "flex w-full items-center justify-between gap-3 border-t border-gray-25 bg-white px-4 py-3", children: [_jsx("span", { className: "text-sm text-gray-500", children: tConversationInbox("thread_detail.view_only_notice") }), _jsx(Button, { type: "primary", size: "small", loading: isJoiningPublicGroup, onClick: handleJoinPublicGroup, children: t("join_group") })] }));
220
253
  }
221
254
  return (_jsxs(MessageFooterContext.Provider, { value: {
222
255
  onSendMessage,
@@ -72,7 +72,7 @@
72
72
  "profile_hint": "Nhấn để xem thông tin",
73
73
  "options_title": "Tuỳ chọn",
74
74
  "input_placeholder": "Nhập tin nhắn...",
75
- "view_only_notice": "Bạn không còn thành viên của nhóm này. Bạn chỉ có thể xem lại nội dung trò chuyện.",
75
+ "view_only_notice": "Bạn cần tham gia nhóm để gửi tin nhắn",
76
76
  "resolve_failed": "Không thể mở cuộc trò chuyện",
77
77
  "more_option": {
78
78
  "toggle": "Tùy chọn khác",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@droppii-org/chat-sdk",
3
- "version": "0.4.11",
3
+ "version": "0.4.12",
4
4
  "description": "Droppii React Chat SDK",
5
5
  "repository": {
6
6
  "type": "git",