@droppii-org/chat-mobile 0.2.78 → 0.2.80
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.
- package/lib/module/components/messages/BubbleTail.js +31 -0
- package/lib/module/components/messages/BubbleTail.js.map +1 -0
- package/lib/module/components/messages/BubbleTailRow.js +46 -0
- package/lib/module/components/messages/BubbleTailRow.js.map +1 -0
- package/lib/module/components/messages/bubbleTail.utils.js +19 -0
- package/lib/module/components/messages/bubbleTail.utils.js.map +1 -0
- package/lib/module/components/messages/fileMessage/index.js +72 -65
- package/lib/module/components/messages/fileMessage/index.js.map +1 -1
- package/lib/module/components/messages/imageMessage/index.js +23 -17
- package/lib/module/components/messages/imageMessage/index.js.map +1 -1
- package/lib/module/components/messages/linkMessage/index.js +11 -23
- package/lib/module/components/messages/linkMessage/index.js.map +1 -1
- package/lib/module/components/messages/mergedMessage/index.js +14 -7
- package/lib/module/components/messages/mergedMessage/index.js.map +1 -1
- package/lib/module/components/messages/quotedMessage/index.js +11 -23
- package/lib/module/components/messages/quotedMessage/index.js.map +1 -1
- package/lib/module/components/messages/revokedMessage/index.js +14 -7
- package/lib/module/components/messages/revokedMessage/index.js.map +1 -1
- package/lib/module/components/messages/stickerMessage/index.js +13 -7
- package/lib/module/components/messages/stickerMessage/index.js.map +1 -1
- package/lib/module/components/messages/textMessage/index.js +11 -26
- package/lib/module/components/messages/textMessage/index.js.map +1 -1
- package/lib/module/components/messages/types.js.map +1 -1
- package/lib/module/components/messages/videoMessage/index.js +16 -8
- package/lib/module/components/messages/videoMessage/index.js.map +1 -1
- package/lib/module/core/useChatListener.js +11 -0
- package/lib/module/core/useChatListener.js.map +1 -1
- package/lib/module/hooks/groups/useDismissGroup.js +2 -1
- package/lib/module/hooks/groups/useDismissGroup.js.map +1 -1
- package/lib/module/hooks/groups/useGroupAccessGuard.js +145 -0
- package/lib/module/hooks/groups/useGroupAccessGuard.js.map +1 -0
- package/lib/module/screens/ChatInfo/ChatInfoDescriptionRow.js +4 -1
- package/lib/module/screens/ChatInfo/ChatInfoDescriptionRow.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatDetail.js +12 -10
- package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatDetailHeader.js +3 -9
- package/lib/module/screens/chat-detail/ChatDetailHeader.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatListLegend.js +71 -21
- package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
- package/lib/module/screens/chat-detail/legend/LegendChatDay.js +8 -2
- package/lib/module/screens/chat-detail/legend/LegendChatDay.js.map +1 -1
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +38 -13
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
- package/lib/module/screens/inbox/CommunityTab.js +5 -2
- package/lib/module/screens/inbox/CommunityTab.js.map +1 -1
- package/lib/module/screens/inbox/MessagesTab.js +2 -2
- package/lib/module/screens/inbox/MessagesTab.js.map +1 -1
- package/lib/module/store/conversation.js +18 -20
- package/lib/module/store/conversation.js.map +1 -1
- package/lib/module/translation/resources/i18n.js +4 -1
- package/lib/module/translation/resources/i18n.js.map +1 -1
- package/lib/module/utils/conversation.js +4 -1
- package/lib/module/utils/conversation.js.map +1 -1
- package/lib/module/utils/legendListMessage.js +86 -12
- package/lib/module/utils/legendListMessage.js.map +1 -1
- package/lib/module/utils/message.js +19 -1
- package/lib/module/utils/message.js.map +1 -1
- package/lib/module/utils/messageUtils.js +7 -1
- package/lib/module/utils/messageUtils.js.map +1 -1
- package/lib/typescript/src/components/messages/BubbleTail.d.ts +13 -0
- package/lib/typescript/src/components/messages/BubbleTail.d.ts.map +1 -0
- package/lib/typescript/src/components/messages/BubbleTailRow.d.ts +25 -0
- package/lib/typescript/src/components/messages/BubbleTailRow.d.ts.map +1 -0
- package/lib/typescript/src/components/messages/bubbleTail.utils.d.ts +11 -0
- package/lib/typescript/src/components/messages/bubbleTail.utils.d.ts.map +1 -0
- package/lib/typescript/src/components/messages/fileMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/fileMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/imageMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/imageMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/linkMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/linkMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/mergedMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/mergedMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/quotedMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/revokedMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/revokedMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/stickerMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/stickerMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/textMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/textMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/types.d.ts +3 -0
- package/lib/typescript/src/components/messages/types.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/videoMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/videoMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/core/useChatListener.d.ts.map +1 -1
- package/lib/typescript/src/hooks/groups/useDismissGroup.d.ts.map +1 -1
- package/lib/typescript/src/hooks/groups/useGroupAccessGuard.d.ts +10 -0
- package/lib/typescript/src/hooks/groups/useGroupAccessGuard.d.ts.map +1 -0
- package/lib/typescript/src/screens/ChatInfo/ChatInfoDescriptionRow.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetailHeader.d.ts +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetailHeader.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatDay.d.ts +6 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatDay.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +14 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/types.d.ts +0 -1
- package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
- package/lib/typescript/src/store/conversation.d.ts.map +1 -1
- package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
- package/lib/typescript/src/utils/conversation.d.ts.map +1 -1
- package/lib/typescript/src/utils/legendListMessage.d.ts +19 -4
- package/lib/typescript/src/utils/legendListMessage.d.ts.map +1 -1
- package/lib/typescript/src/utils/message.d.ts +17 -0
- package/lib/typescript/src/utils/message.d.ts.map +1 -1
- package/lib/typescript/src/utils/messageUtils.d.ts +1 -0
- package/lib/typescript/src/utils/messageUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/messages/BubbleTail.tsx +35 -0
- package/src/components/messages/BubbleTailRow.tsx +64 -0
- package/src/components/messages/bubbleTail.utils.ts +21 -0
- package/src/components/messages/fileMessage/index.tsx +90 -83
- package/src/components/messages/imageMessage/index.tsx +26 -23
- package/src/components/messages/linkMessage/index.tsx +6 -18
- package/src/components/messages/mergedMessage/index.tsx +27 -15
- package/src/components/messages/quotedMessage/index.tsx +7 -19
- package/src/components/messages/revokedMessage/index.tsx +23 -14
- package/src/components/messages/stickerMessage/index.tsx +16 -11
- package/src/components/messages/textMessage/index.tsx +6 -22
- package/src/components/messages/types.ts +3 -0
- package/src/components/messages/videoMessage/index.tsx +13 -10
- package/src/core/useChatListener.ts +14 -0
- package/src/hooks/groups/useDismissGroup.tsx +1 -0
- package/src/hooks/groups/useGroupAccessGuard.ts +182 -0
- package/src/screens/ChatInfo/ChatInfoDescriptionRow.tsx +5 -1
- package/src/screens/chat-detail/ChatDetail.tsx +11 -13
- package/src/screens/chat-detail/ChatDetailHeader.tsx +2 -6
- package/src/screens/chat-detail/ChatListLegend.tsx +97 -28
- package/src/screens/chat-detail/legend/LegendChatDay.tsx +25 -15
- package/src/screens/chat-detail/legend/LegendChatMessage.tsx +62 -12
- package/src/screens/chat-detail/types.ts +0 -1
- package/src/screens/inbox/CommunityTab.tsx +2 -2
- package/src/screens/inbox/MessagesTab.tsx +1 -1
- package/src/store/conversation.ts +14 -18
- package/src/translation/resources/i18n.ts +4 -0
- package/src/utils/conversation.ts +6 -3
- package/src/utils/legendListMessage.ts +123 -14
- package/src/utils/message.ts +19 -1
- package/src/utils/messageUtils.ts +9 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { MessageItem } from '@droppii/openim-rn-client-sdk';
|
|
3
3
|
import type { MediaItem } from '../../../hooks/useMediaViewer';
|
|
4
|
+
import type { GroupPosition } from '../../../utils/legendListMessage';
|
|
4
5
|
interface LegendChatMessageProps {
|
|
5
6
|
message: MessageItem;
|
|
6
7
|
isOutgoing: boolean;
|
|
@@ -12,7 +13,19 @@ interface LegendChatMessageProps {
|
|
|
12
13
|
onLongPress?: () => void;
|
|
13
14
|
customMessageItemFactory?: (m: MessageItem) => ReactNode;
|
|
14
15
|
isHighlighted?: boolean;
|
|
16
|
+
/** Sender name above the bubble — first message of an incoming cluster. */
|
|
17
|
+
showName?: boolean;
|
|
18
|
+
/** Sender avatar beside the bubble — last message of an incoming cluster. */
|
|
19
|
+
showAvatar?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Reserve the avatar column. True for every incoming message in a group
|
|
22
|
+
* conversation, not just the one carrying the avatar, so that the middle of
|
|
23
|
+
* a cluster stays aligned with its last message.
|
|
24
|
+
*/
|
|
25
|
+
showSenderGutter?: boolean;
|
|
26
|
+
/** Position within its same-sender cluster — drives the bubble tail. */
|
|
27
|
+
groupPosition?: GroupPosition;
|
|
15
28
|
}
|
|
16
|
-
export declare const LegendChatMessage: import("react").MemoExoticComponent<({ message, isOutgoing, createdAtTime, onMediaPress, onPressUrl, onRetry, onPress, onLongPress, customMessageItemFactory, isHighlighted, }: LegendChatMessageProps) => string | number | bigint | true | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode>> | import("react").JSX.Element>;
|
|
29
|
+
export declare const LegendChatMessage: import("react").MemoExoticComponent<({ message, isOutgoing, createdAtTime, onMediaPress, onPressUrl, onRetry, onPress, onLongPress, customMessageItemFactory, isHighlighted, showName, showAvatar, showSenderGutter, groupPosition, }: LegendChatMessageProps) => string | number | bigint | true | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode>> | import("react").JSX.Element>;
|
|
17
30
|
export {};
|
|
18
31
|
//# sourceMappingURL=LegendChatMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegendChatMessage.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/legend/LegendChatMessage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LegendChatMessage.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/legend/LegendChatMessage.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAoC,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAGjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAe/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAStE,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,wBAAwB,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,SAAS,CAAC;IACzD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,wEAAwE;IACxE,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AA4BD,eAAO,MAAM,iBAAiB,yOAgBzB,sBAAsB,wRA4F1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/screens/chat-detail/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACZ,MAAM,+BAA+B,CAAC;AAEvC,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,GAAG,YAAY,CAAC;AAE9E,oBAAY,yBAAyB;IACnC,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,iBAAiB,sBAAsB;CACxC;AAED,oBAAY,wBAAwB;IAClC,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,WAAW,gBAAgB;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,wBAAwB,GAAG,yBAAyB,CAAC;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,EAAE,EAAE,wBAAwB,CAAC;CAC9B;AACD,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,EAAE,EAAE,yBAAyB,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/screens/chat-detail/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../src/store/conversation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,KAAK,cAAc,GAAG,MAAM,CAAC;AAE7B,MAAM,WAAW,iBAAiB;IAChC,qBAAqB,CAAC,EAAE,cAAc,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CACpB,EAAE,CAAC,EAAE,cAAc,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAAC;IACR,sBAAsB,IAAI,gBAAgB,GAAG,SAAS,CAAC;IACvD,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAC9C,6FAA6F;IAC7F,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAC9E,mBAAmB,CAAC,aAAa,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;IAC7D;;;OAGG;IACH,kBAAkB,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7C,sCAAsC;IACtC,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../src/store/conversation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,KAAK,cAAc,GAAG,MAAM,CAAC;AAE7B,MAAM,WAAW,iBAAiB;IAChC,qBAAqB,CAAC,EAAE,cAAc,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CACpB,EAAE,CAAC,EAAE,cAAc,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAAC;IACR,sBAAsB,IAAI,gBAAgB,GAAG,SAAS,CAAC;IACvD,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAC9C,6FAA6F;IAC7F,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAC9E,mBAAmB,CAAC,aAAa,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;IAC7D;;;OAGG;IACH,kBAAkB,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7C,sCAAsC;IACtC,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,eAAO,MAAM,oBAAoB,gFAoE9B,CAAC;AAEJ,eAAO,MAAM,eAAe,GAAI,IAAI,MAAM,KAAG,gBAAgB,GAAG,SAE/D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../../../src/translation/resources/i18n.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../../../src/translation/resources/i18n.ts"],"names":[],"mappings":";;;AAyNA,wBAEE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../src/utils/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAC;AAEvC,eAAO,MAAM,mBAAmB,GAC9B,GAAG,gBAAgB,EACnB,GAAG,gBAAgB,WAcpB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,aAAa,WAAW,EACxB,WAAW,MAAM,EACjB,aAAa,MAAM,WAUpB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC;;;
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../src/utils/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAC;AAEvC,eAAO,MAAM,mBAAmB,GAC9B,GAAG,gBAAgB,EACnB,GAAG,gBAAgB,WAcpB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,aAAa,WAAW,EACxB,WAAW,MAAM,EACjB,aAAa,MAAM,WAUpB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC;;;CAQrE,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,eAAe,gBAAgB,QAWvD,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,eAAe,IAAI,CAAC,gBAAgB,EAAE,kBAAkB,GAAG,UAAU,CAAC,YAGvE,CAAC"}
|
|
@@ -3,18 +3,33 @@ import { type MessageItem } from '@droppii/openim-rn-client-sdk';
|
|
|
3
3
|
* Extract message text based on content type
|
|
4
4
|
*/
|
|
5
5
|
export declare const getMessageText: (message: MessageItem) => string;
|
|
6
|
+
/** Where a message sits inside its run of consecutive same-sender messages. */
|
|
7
|
+
export type GroupPosition = 'first' | 'middle' | 'last' | 'solo';
|
|
6
8
|
export interface PrecomputedMessageData {
|
|
7
9
|
messageId: string;
|
|
8
10
|
dayStart: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* More than GROUP_TIME_GAP has passed since the previous message. The list
|
|
13
|
+
* marks these with a time label: the cluster break is real but, unlike a day
|
|
14
|
+
* change, nothing else on screen would show why the run stopped.
|
|
15
|
+
*/
|
|
16
|
+
timeBreak: boolean;
|
|
9
17
|
createdAt: number;
|
|
18
|
+
groupPosition: GroupPosition;
|
|
19
|
+
}
|
|
20
|
+
export interface PrecomputeOptions {
|
|
21
|
+
isBotConversation?: boolean;
|
|
22
|
+
currentUserId?: string;
|
|
10
23
|
}
|
|
11
24
|
/**
|
|
12
|
-
* Precompute
|
|
13
|
-
*
|
|
25
|
+
* Precompute per-message render data (day dividers + cluster position) so
|
|
26
|
+
* renderItem stays allocation-free.
|
|
14
27
|
*
|
|
15
|
-
*
|
|
28
|
+
* Runs in two passes: day starts first, because cluster boundaries depend on
|
|
29
|
+
* them — a divider between two messages separates them however close in time
|
|
30
|
+
* they are.
|
|
16
31
|
*/
|
|
17
|
-
export declare const precomputeLegendListData: (messages: MessageItem[]) => Map<string, PrecomputedMessageData>;
|
|
32
|
+
export declare const precomputeLegendListData: (messages: MessageItem[], { isBotConversation, currentUserId }?: PrecomputeOptions) => Map<string, PrecomputedMessageData>;
|
|
18
33
|
/**
|
|
19
34
|
* Legacy: Use precomputeLegendListData instead
|
|
20
35
|
* Kept for backward compatibility
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legendListMessage.d.ts","sourceRoot":"","sources":["../../../../src/utils/legendListMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"legendListMessage.d.ts","sourceRoot":"","sources":["../../../../src/utils/legendListMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAI9E;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,WAAW,KAAG,MAkCrD,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;CAC9B;AAsCD,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,GACnC,UAAU,WAAW,EAAE,EACvB,uCAA8C,iBAAsB,KACnE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CA6EpC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAC3B,UAAU,WAAW,EAAE,KACtB,GAAG,CAAC,MAAM,EAAE,OAAO,CAYrB,CAAC"}
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import { type ConversationItem, type MessageItem } from '@droppii/openim-rn-client-sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Canonical timestamp for a message. `sendTime` is 0 until the SDK stamps an
|
|
4
|
+
* outgoing message, so `createTime` covers the in-flight window. This is the
|
|
5
|
+
* key the list is sorted by — anything reasoning about message order must use
|
|
6
|
+
* it too, or it will disagree with the order actually rendered.
|
|
7
|
+
*/
|
|
8
|
+
export declare const getMessageTime: (message: MessageItem) => number;
|
|
9
|
+
/**
|
|
10
|
+
* Stable id for a message inside a rendered list.
|
|
11
|
+
*
|
|
12
|
+
* A message that has not round-tripped through the server yet may carry
|
|
13
|
+
* neither id, so position and timestamp stand in. Every consumer that looks a
|
|
14
|
+
* message up by id must derive it the same way — the precompute map is keyed
|
|
15
|
+
* on this, so a divergent formula silently misses and the message renders
|
|
16
|
+
* without its day divider or cluster position.
|
|
17
|
+
*/
|
|
18
|
+
export declare const getMessageRenderId: (message: MessageItem, index: number) => string;
|
|
2
19
|
export declare const mergeMessages: (current: MessageItem[], incoming: MessageItem[]) => MessageItem[];
|
|
3
20
|
export declare const normalizeCreatedMessage: (message: MessageItem | string) => MessageItem;
|
|
4
21
|
export type HistoryPaginationAnchor = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/utils/message.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/utils/message.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;AAGvC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,WAAW,WACN,CAAC;AAK9C;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,EAAE,OAAO,MAAM,WACA,CAAC;AAEvE,eAAO,MAAM,aAAa,GACxB,SAAS,WAAW,EAAE,EACtB,UAAU,WAAW,EAAE,KACtB,WAAW,EAab,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,SAAS,WAAW,GAAG,MAAM,KAC5B,WAYF,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,SAAS;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAChC,kBAAkB,WAAW,KAC5B,MAMF,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,UAAU,WAAW,EAAE,KACtB,uBAAuB,GAAG,IAkB5B,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,SAAS,WAAW,EAAE,EACtB,UAAU,WAAW,EAAE,KACtB,OASF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,SAAS,WAAW,EACpB,iBAAiB,MAAM,EACvB,eAAe,MAAM,KACpB,OA2BF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,eAAe,gBAAgB;;;CAW5D,CAAC"}
|
|
@@ -9,6 +9,7 @@ export declare const GROUP_NOTIFICATION_TEXT: Partial<Record<MessageType, {
|
|
|
9
9
|
previewKey: string;
|
|
10
10
|
bySenderKey: string;
|
|
11
11
|
}>>;
|
|
12
|
+
export declare const GROUP_NOTIFICATION_TYPES: MessageType[];
|
|
12
13
|
export interface ResolvedNotificationText {
|
|
13
14
|
previewKey: string;
|
|
14
15
|
bySenderKey: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageUtils.d.ts","sourceRoot":"","sources":["../../../../src/utils/messageUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,WAAW,EAEX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,KAAG,OACL,CAAC;AAKpD,eAAO,MAAM,uBAAuB,EAAE,OAAO,CAC3C,MAAM,CAAC,WAAW,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAqEjE,CAAC;
|
|
1
|
+
{"version":3,"file":"messageUtils.d.ts","sourceRoot":"","sources":["../../../../src/utils/messageUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,WAAW,EAEX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,KAAG,OACL,CAAC;AAKpD,eAAO,MAAM,uBAAuB,EAAE,OAAO,CAC3C,MAAM,CAAC,WAAW,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAqEjE,CAAC;AAMF,eAAO,MAAM,wBAAwB,EAEpB,WAAW,EAAE,CAAC;AA2B/B,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAQD,eAAO,MAAM,uBAAuB,GAClC,SAAS,WAAW,KACnB,wBAAwB,GAAG,SA8D7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,KAAG,MAYzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,UAAU,WAAW,KAAG,MAyFzD,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,UAAU,WAAW,KACpB,SAUF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,UAAU,WAAW,KACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAGrC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,sBAAsB,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAmBD,eAAO,MAAM,uBAAuB,GAClC,SAAS,WAAW,KACnB,oBA0DF,CAAC;AAKF,eAAO,MAAM,6BAA6B,GACxC,SAAS,WAAW,KACnB,MAAM,GAAG,SAaX,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,SAAS,WAAW,EACpB,gBAAgB,MAAM,EACtB,eAAe,gBAAgB,KAC9B,MAUF,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,eAAO,MAAM,kBAAkB,GAAI,0EAKhC,wBAAwB,KAAG,MAyB7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,WAAW,EACrB,gBAAgB,MAAM,EACtB,eAAe,gBAAgB,EAC/B,SAAS,OAAO,KACf,MAOF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,YAAY,GAAG,SAS7D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,WAAW,MAAM,KAAG,MAUhE,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { memo } from 'react';
|
|
2
|
+
import Svg, { Path } from 'react-native-svg';
|
|
3
|
+
|
|
4
|
+
export const TAIL_WIDTH = 4;
|
|
5
|
+
const TAIL_HEIGHT = 18;
|
|
6
|
+
|
|
7
|
+
// Traced from the design export (Vector 2.svg): a straight vertical edge that
|
|
8
|
+
// continues the bubble's side, flaring outward toward the bottom.
|
|
9
|
+
const TAIL_PATH =
|
|
10
|
+
'M2.6202 18H0V0C0.482375 4.5 0.657308 10.5 3.03348 14C4.56838 16.2608 4.15936 18 2.6202 18Z';
|
|
11
|
+
|
|
12
|
+
export interface BubbleTailProps {
|
|
13
|
+
/**
|
|
14
|
+
* Solid bubble colour. The export carries fill-opacity 0.1, but
|
|
15
|
+
* CHAT_BUBBLE_COLORS is already flattened — reusing the translucent fill here
|
|
16
|
+
* would render the tail a different shade from the bubble it joins.
|
|
17
|
+
*/
|
|
18
|
+
color: string;
|
|
19
|
+
/** Side of the bubble the tail hangs off. */
|
|
20
|
+
side: 'left' | 'right';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const BubbleTail = memo(({ color, side }: BubbleTailProps) => (
|
|
24
|
+
<Svg
|
|
25
|
+
width={TAIL_WIDTH}
|
|
26
|
+
height={TAIL_HEIGHT}
|
|
27
|
+
viewBox={`0 0 ${TAIL_WIDTH} ${TAIL_HEIGHT}`}
|
|
28
|
+
fill="none"
|
|
29
|
+
style={side === 'left' ? { transform: [{ scaleX: -1 }] } : undefined}
|
|
30
|
+
>
|
|
31
|
+
<Path d={TAIL_PATH} fill={color} />
|
|
32
|
+
</Svg>
|
|
33
|
+
));
|
|
34
|
+
|
|
35
|
+
BubbleTail.displayName = 'BubbleTail';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { memo, type PropsWithChildren } from 'react';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
import { KContainer } from '@droppii/libs';
|
|
4
|
+
import { BubbleTail, TAIL_WIDTH } from './BubbleTail';
|
|
5
|
+
import { hasBubbleTail } from './bubbleTail.utils';
|
|
6
|
+
import { CHAT_BUBBLE_COLORS } from '../../screens/chat-detail/constants';
|
|
7
|
+
import type { GroupPosition } from '../../utils/legendListMessage';
|
|
8
|
+
|
|
9
|
+
export type BubbleTailRowProps = PropsWithChildren<{
|
|
10
|
+
isOutgoing: boolean;
|
|
11
|
+
groupPosition?: GroupPosition;
|
|
12
|
+
/**
|
|
13
|
+
* Set false for media bubbles, which carry no tail but still need the gutter
|
|
14
|
+
* so they line up with the text bubbles around them.
|
|
15
|
+
*/
|
|
16
|
+
withTail?: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Places the tail beside the bubble that closes a cluster.
|
|
21
|
+
*
|
|
22
|
+
* The gutter on the tail side is always TAIL_WIDTH wide, whether or not it
|
|
23
|
+
* actually holds a tail. That keeps every bubble in a cluster starting at the
|
|
24
|
+
* same offset while leaving the row's own padding intact — the tail occupies
|
|
25
|
+
* reserved space rather than overhanging into the margin.
|
|
26
|
+
*
|
|
27
|
+
* The tail is a real sibling rather than an absolutely positioned overlay: it
|
|
28
|
+
* sits outside the bubble's edge, and `overflow: visible` is unreliable on
|
|
29
|
+
* Android for views carrying elevation — which the neighbouring pin badge does.
|
|
30
|
+
*/
|
|
31
|
+
export const BubbleTailRow = memo(
|
|
32
|
+
({
|
|
33
|
+
isOutgoing,
|
|
34
|
+
groupPosition,
|
|
35
|
+
withTail = true,
|
|
36
|
+
children,
|
|
37
|
+
}: BubbleTailRowProps) => {
|
|
38
|
+
const gutter =
|
|
39
|
+
withTail && hasBubbleTail(groupPosition) ? (
|
|
40
|
+
<BubbleTail
|
|
41
|
+
side={isOutgoing ? 'right' : 'left'}
|
|
42
|
+
color={
|
|
43
|
+
isOutgoing ? CHAT_BUBBLE_COLORS.sent : CHAT_BUBBLE_COLORS.received
|
|
44
|
+
}
|
|
45
|
+
/>
|
|
46
|
+
) : (
|
|
47
|
+
<KContainer.View style={styles.gutter} />
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<KContainer.View row alignItems="flex-end">
|
|
52
|
+
{!isOutgoing && gutter}
|
|
53
|
+
{children}
|
|
54
|
+
{isOutgoing && gutter}
|
|
55
|
+
</KContainer.View>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
BubbleTailRow.displayName = 'BubbleTailRow';
|
|
61
|
+
|
|
62
|
+
const styles = StyleSheet.create({
|
|
63
|
+
gutter: { width: TAIL_WIDTH },
|
|
64
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ViewStyle } from 'react-native';
|
|
2
|
+
import type { GroupPosition } from '../../utils/legendListMessage';
|
|
3
|
+
|
|
4
|
+
/** Only the message closing a cluster carries a tail. */
|
|
5
|
+
export const hasBubbleTail = (position?: GroupPosition): boolean =>
|
|
6
|
+
position === 'last' || position === 'solo';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The corner the tail hangs off must be square, otherwise the tail's straight
|
|
10
|
+
* 18px edge meets the bubble's rounded corner and leaves a visible notch.
|
|
11
|
+
* Every other corner keeps its normal radius.
|
|
12
|
+
*/
|
|
13
|
+
export const getTailCornerStyle = (
|
|
14
|
+
isOutgoing: boolean,
|
|
15
|
+
position?: GroupPosition
|
|
16
|
+
): ViewStyle | undefined => {
|
|
17
|
+
if (!hasBubbleTail(position)) return undefined;
|
|
18
|
+
return isOutgoing
|
|
19
|
+
? { borderBottomRightRadius: 0 }
|
|
20
|
+
: { borderBottomLeftRadius: 0 };
|
|
21
|
+
};
|
|
@@ -3,6 +3,8 @@ import { StyleSheet } from 'react-native';
|
|
|
3
3
|
import { KContainer, KImage, KLabel, KColors } from '@droppii/libs';
|
|
4
4
|
import { CHAT_BUBBLE_COLORS } from '../../../screens/chat-detail/constants';
|
|
5
5
|
import { messageStyles } from '../styles';
|
|
6
|
+
import { getTailCornerStyle } from '../bubbleTail.utils';
|
|
7
|
+
import { BubbleTailRow } from '../BubbleTailRow';
|
|
6
8
|
import type { BaseLegendMessageProps } from '../types';
|
|
7
9
|
import { useFileDownload } from '../../../hooks/useFileDownload';
|
|
8
10
|
import {
|
|
@@ -12,7 +14,7 @@ import {
|
|
|
12
14
|
} from '../../../utils/imageUtils';
|
|
13
15
|
import { trans } from '../../../translation';
|
|
14
16
|
export const FileMessage = memo(
|
|
15
|
-
({ message, isOutgoing }: BaseLegendMessageProps) => {
|
|
17
|
+
({ message, isOutgoing, groupPosition }: BaseLegendMessageProps) => {
|
|
16
18
|
const fileName = message.fileElem?.fileName || '[File]';
|
|
17
19
|
const fileSize = message.fileElem?.fileSize ?? 0;
|
|
18
20
|
const url =
|
|
@@ -49,97 +51,102 @@ export const FileMessage = memo(
|
|
|
49
51
|
const isDownloading = state.status === 'downloading';
|
|
50
52
|
|
|
51
53
|
return (
|
|
52
|
-
<
|
|
53
|
-
padding={'0.5rem'}
|
|
54
|
-
style={[
|
|
55
|
-
styles.wrapper,
|
|
56
|
-
isOutgoing ? messageStyles.bubbleSent : messageStyles.bubbleReceived,
|
|
57
|
-
]}
|
|
58
|
-
>
|
|
54
|
+
<BubbleTailRow isOutgoing={isOutgoing} groupPosition={groupPosition}>
|
|
59
55
|
<KContainer.View
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
padding={'0.5rem'}
|
|
57
|
+
style={[
|
|
58
|
+
styles.wrapper,
|
|
59
|
+
isOutgoing
|
|
60
|
+
? messageStyles.bubbleSent
|
|
61
|
+
: messageStyles.bubbleReceived,
|
|
62
|
+
getTailCornerStyle(isOutgoing, groupPosition),
|
|
63
|
+
]}
|
|
66
64
|
>
|
|
67
|
-
<KContainer.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
>
|
|
76
|
-
<KContainer.
|
|
65
|
+
<KContainer.View
|
|
66
|
+
row
|
|
67
|
+
alignItems
|
|
68
|
+
br={'3x'}
|
|
69
|
+
paddingR={'0.75rem'}
|
|
70
|
+
paddingV={'0.25rem'}
|
|
71
|
+
background={KColors.white}
|
|
72
|
+
>
|
|
73
|
+
<KContainer.VisibleView visible={isDownloading}>
|
|
74
|
+
<KContainer.Touchable
|
|
77
75
|
center
|
|
78
76
|
br="round"
|
|
79
|
-
style={styles.
|
|
80
|
-
width={
|
|
81
|
-
height={
|
|
77
|
+
style={styles.cancelBtn}
|
|
78
|
+
width={32}
|
|
79
|
+
height={32}
|
|
80
|
+
onPress={handleDownload}
|
|
82
81
|
>
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
82
|
+
<KContainer.View
|
|
83
|
+
center
|
|
84
|
+
br="round"
|
|
85
|
+
style={styles.cancelBtnIconContainer}
|
|
86
|
+
width={26}
|
|
87
|
+
height={26}
|
|
88
|
+
>
|
|
89
|
+
<KImage.VectorIcons
|
|
90
|
+
name="close"
|
|
91
|
+
provider="MaterialCommunityIcons"
|
|
92
|
+
size={24}
|
|
93
|
+
color={KColors.white}
|
|
94
|
+
/>
|
|
95
|
+
</KContainer.View>
|
|
96
|
+
</KContainer.Touchable>
|
|
97
|
+
</KContainer.VisibleView>
|
|
98
|
+
<KContainer.VisibleView visible={!isDownloading}>
|
|
99
|
+
<KImage.Base
|
|
100
|
+
uri={iconSource}
|
|
101
|
+
style={styles.fileIcon}
|
|
102
|
+
resizeMode="contain"
|
|
103
|
+
/>
|
|
104
|
+
</KContainer.VisibleView>
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
106
|
+
{/* File name + size/progress */}
|
|
107
|
+
<KContainer.View flexS={1}>
|
|
108
|
+
<KLabel.Text
|
|
109
|
+
typo="TextSmMedium"
|
|
110
|
+
color={CHAT_BUBBLE_COLORS.text}
|
|
111
|
+
numberOfLines={1}
|
|
112
|
+
ellipsizeMode="middle"
|
|
113
|
+
>
|
|
114
|
+
{fileName}
|
|
115
|
+
</KLabel.Text>
|
|
116
|
+
<KLabel.Text
|
|
117
|
+
typo="TextXsNormal"
|
|
118
|
+
color={subtitleColor}
|
|
119
|
+
numberOfLines={1}
|
|
120
|
+
>
|
|
121
|
+
{subtitle}
|
|
122
|
+
</KLabel.Text>
|
|
123
|
+
</KContainer.View>
|
|
118
124
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
{/* Eye (view) button */}
|
|
126
|
+
<KImage.VectorIcons
|
|
127
|
+
name="eye-outline"
|
|
128
|
+
provider="MaterialCommunityIcons"
|
|
129
|
+
onPress={handleView}
|
|
130
|
+
size={20}
|
|
131
|
+
color={KColors.palette.gray.w600}
|
|
132
|
+
containerStyle={styles.viewIcon}
|
|
133
|
+
/>
|
|
128
134
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
<KImage.VectorIcons
|
|
136
|
+
name={'download-o'}
|
|
137
|
+
provider="DroppiiNew"
|
|
138
|
+
onPress={isDownloading ? undefined : handleDownload}
|
|
139
|
+
size={20}
|
|
140
|
+
color={
|
|
141
|
+
state.status === 'error'
|
|
142
|
+
? (KColors.palette.danger?.w400 ?? '#FF3B30')
|
|
143
|
+
: KColors.palette.gray.w600
|
|
144
|
+
}
|
|
145
|
+
containerStyle={isDownloading ? styles.disabledIcon : undefined}
|
|
146
|
+
/>
|
|
147
|
+
</KContainer.View>
|
|
141
148
|
</KContainer.View>
|
|
142
|
-
</
|
|
149
|
+
</BubbleTailRow>
|
|
143
150
|
);
|
|
144
151
|
}
|
|
145
152
|
);
|
|
@@ -3,6 +3,7 @@ import { StyleSheet, useWindowDimensions } from 'react-native';
|
|
|
3
3
|
import { KContainer, KImage } from '@droppii/libs';
|
|
4
4
|
import ChatImageDimens from '../../../utils/chatImageDimens';
|
|
5
5
|
import { messageStyles } from '../styles';
|
|
6
|
+
import { BubbleTailRow } from '../BubbleTailRow';
|
|
6
7
|
import type { BaseLegendMessageProps } from '../types';
|
|
7
8
|
const DEFAULT_DIMS = { width: 300, height: 300 };
|
|
8
9
|
|
|
@@ -72,7 +73,7 @@ export const resolveImageDisplayDims = (
|
|
|
72
73
|
};
|
|
73
74
|
|
|
74
75
|
export const ImageMessage = memo(
|
|
75
|
-
({ message, onMediaPress }: BaseLegendMessageProps) => {
|
|
76
|
+
({ message, isOutgoing, onMediaPress }: BaseLegendMessageProps) => {
|
|
76
77
|
const windowWidth = useWindowDimensions().width;
|
|
77
78
|
const [isLoading, setIsLoading] = useState(true);
|
|
78
79
|
const pictureElem = (message as any).pictureElem;
|
|
@@ -130,28 +131,30 @@ export const ImageMessage = memo(
|
|
|
130
131
|
);
|
|
131
132
|
|
|
132
133
|
return (
|
|
133
|
-
<
|
|
134
|
-
<KContainer.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
134
|
+
<BubbleTailRow isOutgoing={isOutgoing} withTail={false}>
|
|
135
|
+
<KContainer.View style={styles.wrapper}>
|
|
136
|
+
<KContainer.Touchable
|
|
137
|
+
onPress={handlePress}
|
|
138
|
+
style={[
|
|
139
|
+
messageStyles.imageBubble,
|
|
140
|
+
styles.imageContainer,
|
|
141
|
+
{
|
|
142
|
+
width: imageDimensions.width,
|
|
143
|
+
height: imageDimensions.height,
|
|
144
|
+
},
|
|
145
|
+
]}
|
|
146
|
+
>
|
|
147
|
+
<KImage.Base
|
|
148
|
+
uri={optimizedUrl}
|
|
149
|
+
width={imageDimensions.width}
|
|
150
|
+
height={imageDimensions.height}
|
|
151
|
+
style={[messageStyles.imageBubble]}
|
|
152
|
+
onLoad={handleLoad}
|
|
153
|
+
/>
|
|
154
|
+
{isLoading && <KContainer.View style={styles.skeleton} />}
|
|
155
|
+
</KContainer.Touchable>
|
|
156
|
+
</KContainer.View>
|
|
157
|
+
</BubbleTailRow>
|
|
155
158
|
);
|
|
156
159
|
}
|
|
157
160
|
);
|