@droppii-org/chat-mobile 0.2.79 → 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/hooks/groups/useDismissGroup.js +2 -1
- package/lib/module/hooks/groups/useDismissGroup.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/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 +6 -0
- 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/hooks/groups/useDismissGroup.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/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/hooks/groups/useDismissGroup.tsx +1 -0
- 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/utils/legendListMessage.ts +123 -14
- package/src/utils/message.ts +19 -1
- package/src/utils/messageUtils.ts +8 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type PropsWithChildren } from 'react';
|
|
2
|
+
import type { GroupPosition } from '../../utils/legendListMessage';
|
|
3
|
+
export type BubbleTailRowProps = PropsWithChildren<{
|
|
4
|
+
isOutgoing: boolean;
|
|
5
|
+
groupPosition?: GroupPosition;
|
|
6
|
+
/**
|
|
7
|
+
* Set false for media bubbles, which carry no tail but still need the gutter
|
|
8
|
+
* so they line up with the text bubbles around them.
|
|
9
|
+
*/
|
|
10
|
+
withTail?: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
/**
|
|
13
|
+
* Places the tail beside the bubble that closes a cluster.
|
|
14
|
+
*
|
|
15
|
+
* The gutter on the tail side is always TAIL_WIDTH wide, whether or not it
|
|
16
|
+
* actually holds a tail. That keeps every bubble in a cluster starting at the
|
|
17
|
+
* same offset while leaving the row's own padding intact — the tail occupies
|
|
18
|
+
* reserved space rather than overhanging into the margin.
|
|
19
|
+
*
|
|
20
|
+
* The tail is a real sibling rather than an absolutely positioned overlay: it
|
|
21
|
+
* sits outside the bubble's edge, and `overflow: visible` is unreliable on
|
|
22
|
+
* Android for views carrying elevation — which the neighbouring pin badge does.
|
|
23
|
+
*/
|
|
24
|
+
export declare const BubbleTailRow: import("react").MemoExoticComponent<({ isOutgoing, groupPosition, withTail, children, }: BubbleTailRowProps) => import("react").JSX.Element>;
|
|
25
|
+
//# sourceMappingURL=BubbleTailRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BubbleTailRow.d.ts","sourceRoot":"","sources":["../../../../../src/components/messages/BubbleTailRow.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAMrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;IACjD,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,2FAMrB,kBAAkB,iCAqBtB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ViewStyle } from 'react-native';
|
|
2
|
+
import type { GroupPosition } from '../../utils/legendListMessage';
|
|
3
|
+
/** Only the message closing a cluster carries a tail. */
|
|
4
|
+
export declare const hasBubbleTail: (position?: GroupPosition) => boolean;
|
|
5
|
+
/**
|
|
6
|
+
* The corner the tail hangs off must be square, otherwise the tail's straight
|
|
7
|
+
* 18px edge meets the bubble's rounded corner and leaves a visible notch.
|
|
8
|
+
* Every other corner keeps its normal radius.
|
|
9
|
+
*/
|
|
10
|
+
export declare const getTailCornerStyle: (isOutgoing: boolean, position?: GroupPosition) => ViewStyle | undefined;
|
|
11
|
+
//# sourceMappingURL=bubbleTail.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bubbleTail.utils.d.ts","sourceRoot":"","sources":["../../../../../src/components/messages/bubbleTail.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEnE,yDAAyD;AACzD,eAAO,MAAM,aAAa,GAAI,WAAW,aAAa,KAAG,OACb,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,YAAY,OAAO,EACnB,WAAW,aAAa,KACvB,SAAS,GAAG,SAKd,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BaseLegendMessageProps } from '../types';
|
|
2
|
-
export declare const FileMessage: import("react").MemoExoticComponent<({ message, isOutgoing }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
2
|
+
export declare const FileMessage: import("react").MemoExoticComponent<({ message, isOutgoing, groupPosition }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/fileMessage/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/fileMessage/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAQvD,eAAO,MAAM,WAAW,+EACmB,sBAAsB,iCAuIhE,CAAC"}
|
|
@@ -11,5 +11,5 @@ export declare const resolveImageDisplayDims: (message: unknown, windowWidth: nu
|
|
|
11
11
|
width: number;
|
|
12
12
|
height: number;
|
|
13
13
|
};
|
|
14
|
-
export declare const ImageMessage: import("react").MemoExoticComponent<({ message, onMediaPress }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
14
|
+
export declare const ImageMessage: import("react").MemoExoticComponent<({ message, isOutgoing, onMediaPress }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/imageMessage/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/imageMessage/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAgCvD;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,OAAO,EAChB,aAAa,MAAM,KAClB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAuBjC,CAAC;AAEF,eAAO,MAAM,YAAY,8EACiB,sBAAsB,iCAoF/D,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BaseLegendMessageProps } from '../types';
|
|
2
|
-
export declare const LinkMessage: import("react").MemoExoticComponent<({ message, isOutgoing,
|
|
2
|
+
export declare const LinkMessage: import("react").MemoExoticComponent<({ message, isOutgoing, onPressUrl, isHighlighted, groupPosition, }: BaseLegendMessageProps & {
|
|
3
3
|
onPressUrl?: (url: string) => void;
|
|
4
4
|
}) => import("react").JSX.Element>;
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/linkMessage/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/linkMessage/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAmDvD,eAAO,MAAM,WAAW,2GAOnB,sBAAsB,GAAG;IAAE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,iCAsEnE,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BaseLegendMessageProps } from '../types';
|
|
2
|
-
export declare const MergedMessage: import("react").MemoExoticComponent<({ message, isOutgoing, onMediaPress }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
2
|
+
export declare const MergedMessage: import("react").MemoExoticComponent<({ message, isOutgoing, onMediaPress, groupPosition, }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/mergedMessage/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/mergedMessage/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,eAAO,MAAM,aAAa,8FAMrB,sBAAsB,iCAkC1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/quotedMessage/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/quotedMessage/index.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAsBvD,UAAU,kBAAmB,SAAQ,sBAAsB;CAAG;AAE9D,QAAA,MAAM,aAAa,8CAAgB,kBAAkB,iCAyGnD,CAAC;AAIH,eAAe,aAAa,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BaseLegendMessageProps } from '../types';
|
|
2
|
-
export declare const RevokedMessage: import("react").MemoExoticComponent<({ isOutgoing }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
2
|
+
export declare const RevokedMessage: import("react").MemoExoticComponent<({ isOutgoing, groupPosition }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/revokedMessage/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/revokedMessage/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEvD,eAAO,MAAM,cAAc,sEACO,sBAAsB,iCAmBvD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { BaseLegendMessageProps } from '../types';
|
|
2
2
|
export declare const STICKER_SIZE = 120;
|
|
3
|
-
export declare const StickerMessage: import("react").MemoExoticComponent<({ message }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
3
|
+
export declare const StickerMessage: import("react").MemoExoticComponent<({ message, isOutgoing }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/stickerMessage/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/stickerMessage/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAKvD,eAAO,MAAM,YAAY,MAAM,CAAC;AAChC,eAAO,MAAM,cAAc,gEACC,sBAAsB,iCAajD,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BaseLegendMessageProps } from '../types';
|
|
2
|
-
export declare const TextMessage: import("react").MemoExoticComponent<({ message, isOutgoing,
|
|
2
|
+
export declare const TextMessage: import("react").MemoExoticComponent<({ message, isOutgoing, isHighlighted, groupPosition, }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/textMessage/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/textMessage/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,eAAO,MAAM,WAAW,+FAMnB,sBAAsB,iCA0B1B,CAAC"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { MediaItem } from '../../hooks/useMediaViewer';
|
|
2
2
|
import type { MessageItem } from '@droppii/openim-rn-client-sdk';
|
|
3
|
+
import type { GroupPosition } from '../../utils/legendListMessage';
|
|
3
4
|
export interface BaseLegendMessageProps {
|
|
4
5
|
message: MessageItem;
|
|
5
6
|
isOutgoing: boolean;
|
|
6
7
|
createdAtTime: number;
|
|
7
8
|
isHighlighted?: boolean;
|
|
9
|
+
/** Position within its same-sender cluster — drives the bubble tail. */
|
|
10
|
+
groupPosition?: GroupPosition;
|
|
8
11
|
onMediaPress?: (items: MediaItem[], index?: number) => void;
|
|
9
12
|
}
|
|
10
13
|
export declare const formatMessageTime: (createdAt: number) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/components/messages/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/components/messages/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,wEAAwE;IACxE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7D;AAED,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,WAWlD,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BaseLegendMessageProps } from '../types';
|
|
2
|
-
export declare const VideoMessage: import("react").MemoExoticComponent<({ message, onMediaPress }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
2
|
+
export declare const VideoMessage: import("react").MemoExoticComponent<({ message, isOutgoing, onMediaPress }: BaseLegendMessageProps) => import("react").JSX.Element>;
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/videoMessage/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/messages/videoMessage/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAQvD,eAAO,MAAM,YAAY,8EACiB,sBAAsB,iCAsE/D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDismissGroup.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/groups/useDismissGroup.tsx"],"names":[],"mappings":"AAMA,UAAU,oBAAoB;IAC5B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AACD,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,EAAE,oBAAoB;
|
|
1
|
+
{"version":3,"file":"useDismissGroup.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/groups/useDismissGroup.tsx"],"names":[],"mappings":"AAMA,UAAU,oBAAoB;IAC5B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AACD,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,EAAE,oBAAoB;6BA2C9C,MAAM;EA4B1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatListLegend.d.ts","sourceRoot":"","sources":["../../../../../src/screens/chat-detail/ChatListLegend.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AASf,OAAiB,EAKf,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatListLegend.d.ts","sourceRoot":"","sources":["../../../../../src/screens/chat-detail/ChatListLegend.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AASf,OAAiB,EAKf,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAc9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA8C7C,UAAU,2BAA4B,SAAQ,aAAa;IACzD,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACzC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7B,kBAAkB,EAAE,CAAC,IAAI,EAAE;QACzB,QAAQ,EAAE,OAAO,CAAC;QAClB,aAAa,EAAE,OAAO,CAAC;KACxB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,6RAmBtB,2BAA2B,iCA2gB/B,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
interface LegendChatDayProps {
|
|
2
2
|
createdAt: number;
|
|
3
|
+
/**
|
|
4
|
+
* Render just the clock time, without the day. Used where a cluster broke on
|
|
5
|
+
* elapsed time inside a single day — the date is already on screen above.
|
|
6
|
+
*/
|
|
7
|
+
timeOnly?: boolean;
|
|
3
8
|
}
|
|
4
|
-
export declare const LegendChatDay: import("react").MemoExoticComponent<({ createdAt }: LegendChatDayProps) => import("react").JSX.Element>;
|
|
9
|
+
export declare const LegendChatDay: import("react").MemoExoticComponent<({ createdAt, timeOnly }: LegendChatDayProps) => import("react").JSX.Element>;
|
|
5
10
|
export {};
|
|
6
11
|
//# sourceMappingURL=LegendChatDay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegendChatDay.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/legend/LegendChatDay.tsx"],"names":[],"mappings":"AA8CA,UAAU,kBAAkB;IAC1B,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"LegendChatDay.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/legend/LegendChatDay.tsx"],"names":[],"mappings":"AA8CA,UAAU,kBAAkB;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,gEACU,kBAAkB,iCAqBrD,CAAC"}
|
|
@@ -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"}
|
|
@@ -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
|
+
};
|