@droppii-org/chat-mobile 0.2.25 → 0.2.27

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 (132) hide show
  1. package/README.md +113 -0
  2. package/lib/module/components/flows/inputButtons/index.js +3 -6
  3. package/lib/module/components/flows/inputButtons/index.js.map +1 -1
  4. package/lib/module/components/messages/fileMessage/index.js +1 -1
  5. package/lib/module/components/messages/fileMessage/index.js.map +1 -1
  6. package/lib/module/components/messages/imageMessage/index.js +1 -1
  7. package/lib/module/components/messages/imageMessage/index.js.map +1 -1
  8. package/lib/module/components/messages/linkMessage/index.js +7 -7
  9. package/lib/module/components/messages/linkMessage/index.js.map +1 -1
  10. package/lib/module/components/messages/mergedMessage/index.js +5 -8
  11. package/lib/module/components/messages/mergedMessage/index.js.map +1 -1
  12. package/lib/module/components/messages/styles.js +12 -0
  13. package/lib/module/components/messages/styles.js.map +1 -1
  14. package/lib/module/components/messages/textMessage/index.js +10 -7
  15. package/lib/module/components/messages/textMessage/index.js.map +1 -1
  16. package/lib/module/components/messages/videoMessage/index.js +7 -11
  17. package/lib/module/components/messages/videoMessage/index.js.map +1 -1
  18. package/lib/module/core/index.js +3 -0
  19. package/lib/module/core/index.js.map +1 -1
  20. package/lib/module/core/notification/backgroundStatus.js +15 -0
  21. package/lib/module/core/notification/backgroundStatus.js.map +1 -0
  22. package/lib/module/core/notification/index.js +5 -0
  23. package/lib/module/core/notification/index.js.map +1 -0
  24. package/lib/module/core/notification/pushToken.js +23 -0
  25. package/lib/module/core/notification/pushToken.js.map +1 -0
  26. package/lib/module/core/notification/useBackgroundStatusSync.js +16 -0
  27. package/lib/module/core/notification/useBackgroundStatusSync.js.map +1 -0
  28. package/lib/module/hooks/useChatMessages.js +2 -1
  29. package/lib/module/hooks/useChatMessages.js.map +1 -1
  30. package/lib/module/index.js +1 -0
  31. package/lib/module/index.js.map +1 -1
  32. package/lib/module/screens/chat-detail/ChatDetail.js +11 -1
  33. package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
  34. package/lib/module/screens/chat-detail/ChatListLegend.js +21 -14
  35. package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
  36. package/lib/module/screens/chat-detail/constants.js +3 -2
  37. package/lib/module/screens/chat-detail/constants.js.map +1 -1
  38. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +36 -8
  39. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
  40. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxMenu.js +98 -0
  41. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxMenu.js.map +1 -0
  42. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js +110 -0
  43. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js.map +1 -0
  44. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxWrapper.js +64 -0
  45. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxWrapper.js.map +1 -0
  46. package/lib/module/screens/chat-detail/messageToolbox/messageToolbox.utils.js +37 -0
  47. package/lib/module/screens/chat-detail/messageToolbox/messageToolbox.utils.js.map +1 -0
  48. package/lib/module/screens/chat-detail/messageToolbox/types.js +4 -0
  49. package/lib/module/screens/chat-detail/messageToolbox/types.js.map +1 -0
  50. package/lib/module/services/attachmentOrchestrator.js +2 -1
  51. package/lib/module/services/attachmentOrchestrator.js.map +1 -1
  52. package/lib/module/translation/resources/i18n.js +5 -0
  53. package/lib/module/translation/resources/i18n.js.map +1 -1
  54. package/lib/module/utils/promise.js +14 -0
  55. package/lib/module/utils/promise.js.map +1 -0
  56. package/lib/module/utils/ui.js +19 -0
  57. package/lib/module/utils/ui.js.map +1 -0
  58. package/lib/typescript/src/components/flows/inputButtons/index.d.ts.map +1 -1
  59. package/lib/typescript/src/components/messages/fileMessage/index.d.ts.map +1 -1
  60. package/lib/typescript/src/components/messages/mergedMessage/index.d.ts.map +1 -1
  61. package/lib/typescript/src/components/messages/styles.d.ts +15 -3
  62. package/lib/typescript/src/components/messages/styles.d.ts.map +1 -1
  63. package/lib/typescript/src/components/messages/textMessage/index.d.ts.map +1 -1
  64. package/lib/typescript/src/components/messages/videoMessage/index.d.ts.map +1 -1
  65. package/lib/typescript/src/core/index.d.ts +1 -0
  66. package/lib/typescript/src/core/index.d.ts.map +1 -1
  67. package/lib/typescript/src/core/notification/backgroundStatus.d.ts +6 -0
  68. package/lib/typescript/src/core/notification/backgroundStatus.d.ts.map +1 -0
  69. package/lib/typescript/src/core/notification/index.d.ts +3 -0
  70. package/lib/typescript/src/core/notification/index.d.ts.map +1 -0
  71. package/lib/typescript/src/core/notification/pushToken.d.ts +14 -0
  72. package/lib/typescript/src/core/notification/pushToken.d.ts.map +1 -0
  73. package/lib/typescript/src/core/notification/useBackgroundStatusSync.d.ts +2 -0
  74. package/lib/typescript/src/core/notification/useBackgroundStatusSync.d.ts.map +1 -0
  75. package/lib/typescript/src/hooks/useChatMessages.d.ts.map +1 -1
  76. package/lib/typescript/src/index.d.ts +1 -0
  77. package/lib/typescript/src/index.d.ts.map +1 -1
  78. package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
  79. package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts +1 -1
  80. package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts.map +1 -1
  81. package/lib/typescript/src/screens/chat-detail/constants.d.ts +2 -2
  82. package/lib/typescript/src/screens/chat-detail/constants.d.ts.map +1 -1
  83. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +2 -1
  84. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
  85. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxMenu.d.ts +11 -0
  86. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxMenu.d.ts.map +1 -0
  87. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts +10 -0
  88. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts.map +1 -0
  89. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxWrapper.d.ts +11 -0
  90. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxWrapper.d.ts.map +1 -0
  91. package/lib/typescript/src/screens/chat-detail/messageToolbox/messageToolbox.utils.d.ts +18 -0
  92. package/lib/typescript/src/screens/chat-detail/messageToolbox/messageToolbox.utils.d.ts.map +1 -0
  93. package/lib/typescript/src/screens/chat-detail/messageToolbox/types.d.ts +12 -0
  94. package/lib/typescript/src/screens/chat-detail/messageToolbox/types.d.ts.map +1 -0
  95. package/lib/typescript/src/screens/chat-detail/types.d.ts +2 -0
  96. package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
  97. package/lib/typescript/src/services/attachmentOrchestrator.d.ts.map +1 -1
  98. package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
  99. package/lib/typescript/src/utils/promise.d.ts +13 -0
  100. package/lib/typescript/src/utils/promise.d.ts.map +1 -0
  101. package/lib/typescript/src/utils/ui.d.ts +2 -0
  102. package/lib/typescript/src/utils/ui.d.ts.map +1 -0
  103. package/package.json +3 -1
  104. package/src/components/flows/inputButtons/index.tsx +3 -5
  105. package/src/components/messages/fileMessage/index.tsx +0 -1
  106. package/src/components/messages/imageMessage/index.tsx +1 -1
  107. package/src/components/messages/linkMessage/index.tsx +4 -3
  108. package/src/components/messages/mergedMessage/index.tsx +13 -17
  109. package/src/components/messages/styles.ts +12 -0
  110. package/src/components/messages/textMessage/index.tsx +8 -3
  111. package/src/components/messages/videoMessage/index.tsx +8 -10
  112. package/src/core/index.ts +4 -0
  113. package/src/core/notification/backgroundStatus.ts +22 -0
  114. package/src/core/notification/index.ts +5 -0
  115. package/src/core/notification/pushToken.ts +24 -0
  116. package/src/core/notification/useBackgroundStatusSync.ts +18 -0
  117. package/src/hooks/useChatMessages.ts +2 -1
  118. package/src/index.tsx +1 -0
  119. package/src/screens/chat-detail/ChatDetail.tsx +17 -0
  120. package/src/screens/chat-detail/ChatListLegend.tsx +30 -16
  121. package/src/screens/chat-detail/constants.ts +3 -2
  122. package/src/screens/chat-detail/legend/LegendChatMessage.tsx +49 -11
  123. package/src/screens/chat-detail/messageToolbox/MessageToolboxMenu.tsx +114 -0
  124. package/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.tsx +130 -0
  125. package/src/screens/chat-detail/messageToolbox/MessageToolboxWrapper.tsx +99 -0
  126. package/src/screens/chat-detail/messageToolbox/messageToolbox.utils.ts +56 -0
  127. package/src/screens/chat-detail/messageToolbox/types.ts +13 -0
  128. package/src/screens/chat-detail/types.ts +2 -0
  129. package/src/services/attachmentOrchestrator.ts +2 -1
  130. package/src/translation/resources/i18n.ts +5 -0
  131. package/src/utils/promise.ts +18 -0
  132. package/src/utils/ui.ts +23 -0
@@ -0,0 +1,11 @@
1
+ interface MessageToolboxMenuProps {
2
+ showCopyMessage?: boolean;
3
+ showCopyMessageLink?: boolean;
4
+ showRetryMessage?: boolean;
5
+ onCopyMessage: () => void;
6
+ onCopyMessageLink: () => void;
7
+ onRetryMessage: () => void;
8
+ }
9
+ export declare const MessageToolboxMenu: import("react").MemoExoticComponent<({ showCopyMessage, showCopyMessageLink, showRetryMessage, onCopyMessage, onCopyMessageLink, onRetryMessage, }: MessageToolboxMenuProps) => import("react").JSX.Element>;
10
+ export {};
11
+ //# sourceMappingURL=MessageToolboxMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageToolboxMenu.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/messageToolbox/MessageToolboxMenu.tsx"],"names":[],"mappings":"AAWA,UAAU,uBAAuB;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,eAAO,MAAM,kBAAkB,sJAQ1B,uBAAuB,iCA+D3B,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { DMessageItem } from '../../../types/chat';
2
+ import type { MessageToolboxRef } from './types';
3
+ import type { ReactNode } from 'react';
4
+ interface MessageToolboxOverlayProps {
5
+ currentUserId?: string;
6
+ customMessageItemFactory?: (item: DMessageItem) => ReactNode;
7
+ }
8
+ export declare const MessageToolboxOverlay: import("react").ForwardRefExoticComponent<MessageToolboxOverlayProps & import("react").RefAttributes<MessageToolboxRef>>;
9
+ export {};
10
+ //# sourceMappingURL=MessageToolboxOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageToolboxOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAgB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,UAAU,0BAA0B;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wBAAwB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,SAAS,CAAC;CAC9D;AAED,eAAO,MAAM,qBAAqB,0HA8FhC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { MeasuredRect } from './types';
2
+ type MessageToolboxWrapperProps = {
3
+ isOutgoing?: boolean;
4
+ rect: MeasuredRect;
5
+ message?: React.ReactNode;
6
+ reaction?: React.ReactNode;
7
+ toolbox?: React.ReactNode;
8
+ };
9
+ export declare const MessageToolboxWrapper: import("react").MemoExoticComponent<({ isOutgoing, rect, message, reaction, toolbox, }: MessageToolboxWrapperProps) => import("react").JSX.Element>;
10
+ export {};
11
+ //# sourceMappingURL=MessageToolboxWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageToolboxWrapper.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/messageToolbox/MessageToolboxWrapper.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAO5C,KAAK,0BAA0B,GAAG;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,qBAAqB,0FAO7B,0BAA0B,iCA6D9B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { DMessageItem } from '../../../types/chat';
2
+ export declare const isMessageRecalled: (message: DMessageItem) => boolean;
3
+ export declare const isMessageSucceeded: (message: DMessageItem) => boolean;
4
+ export declare const isEligibleForToolbox: (message: DMessageItem) => boolean;
5
+ export declare const isCopyMessageSupported: (message: DMessageItem) => boolean;
6
+ export declare const isCopyMessageLinkSupported: (message: DMessageItem) => boolean;
7
+ export declare const isRetrySupported: (message: DMessageItem) => boolean;
8
+ export declare const getCopyableMessageText: (message: DMessageItem) => string;
9
+ export declare const useMessageToolboxItems: (message?: DMessageItem) => {
10
+ showCopyMessage?: undefined;
11
+ showCopyMessageLink?: undefined;
12
+ showRetryMessage?: undefined;
13
+ } | {
14
+ showCopyMessage: boolean;
15
+ showCopyMessageLink: boolean;
16
+ showRetryMessage: boolean;
17
+ };
18
+ //# sourceMappingURL=messageToolbox.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messageToolbox.utils.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/messageToolbox/messageToolbox.utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAWxD,eAAO,MAAM,iBAAiB,GAAI,SAAS,YAAY,KAAG,OACP,CAAC;AAEpD,eAAO,MAAM,kBAAkB,GAAI,SAAS,YAAY,KAAG,OAEjB,CAAC;AAG3C,eAAO,MAAM,oBAAoB,GAAI,SAAS,YAAY,KAAG,OACD,CAAC;AAE7D,eAAO,MAAM,sBAAsB,GAAI,SAAS,YAAY,KAAG,OAEZ,CAAC;AAGpD,eAAO,MAAM,0BAA0B,GAAI,SAAS,YAAY,KAAG,OACpC,CAAC;AAEhC,eAAO,MAAM,gBAAgB,GAAI,SAAS,YAAY,KAAG,OAChB,CAAC;AAE1C,eAAO,MAAM,sBAAsB,GAAI,SAAS,YAAY,KAAG,MAK9D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,UAAU,YAAY;;;;;;;;CAc5D,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { DMessageItem } from '../../../types/chat';
2
+ export interface MeasuredRect {
3
+ x: number;
4
+ y: number;
5
+ width: number;
6
+ height: number;
7
+ }
8
+ export interface MessageToolboxRef {
9
+ show: (message: DMessageItem, rect: MeasuredRect) => void;
10
+ hide: () => void;
11
+ }
12
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/screens/chat-detail/messageToolbox/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAC1D,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB"}
@@ -2,6 +2,7 @@ import type { ReactNode } from 'react';
2
2
  import type { MediaItem } from '../../hooks/useMediaViewer';
3
3
  import type { DMessageItem } from '../../types/chat';
4
4
  import type { ConversationItem } from '@droppii/openim-rn-client-sdk';
5
+ import type { MeasuredRect } from './messageToolbox/types';
5
6
  export type DChatActionIconProvider = 'MaterialCommunityIcons' | 'DroppiiNew';
6
7
  export interface DChatActionItem {
7
8
  id: string;
@@ -60,6 +61,7 @@ export interface ChatListProps {
60
61
  hasMoreNewer?: boolean;
61
62
  onMediaPress?: (items: MediaItem[], index?: number) => void;
62
63
  onPressUrl?: (url: string) => void;
64
+ onLongPress?: (message: DMessageItem, rect: MeasuredRect) => void;
63
65
  }
64
66
  export interface ChatDetailProps extends Omit<ChatDetailHeaderProps, 'title' | 'subtitle' | 'avatarUri' | 'avatarFullName' | 'applicationType' | 'showAddMember' | 'conversationId'> {
65
67
  conversationId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/screens/chat-detail/types.ts"],"names":[],"mappings":"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"}
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":"attachmentOrchestrator.d.ts","sourceRoot":"","sources":["../../../../src/services/attachmentOrchestrator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,UAAU,EACV,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAS7B,yBAAiB,6BAA6B,CAAC;IAC7C,SAAsB,uBAAuB,CAC3C,WAAW,EAAE,UAAU,EAAE,EACzB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,OAAO,GAAE,qBAAkD,GAC1D,OAAO,CAAC,oBAAoB,CAAC,CA6F/B;CA6MF"}
1
+ {"version":3,"file":"attachmentOrchestrator.d.ts","sourceRoot":"","sources":["../../../../src/services/attachmentOrchestrator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,UAAU,EACV,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAU7B,yBAAiB,6BAA6B,CAAC;IAC7C,SAAsB,uBAAuB,CAC3C,WAAW,EAAE,UAAU,EAAE,EACzB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,OAAO,GAAE,qBAAkD,GAC1D,OAAO,CAAC,oBAAoB,CAAC,CA6F/B;CA6MF"}
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../../../src/translation/resources/i18n.ts"],"names":[],"mappings":";;;AAwCA,wBAEE"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../../../src/translation/resources/i18n.ts"],"names":[],"mappings":";;;AA6CA,wBAEE"}
@@ -0,0 +1,13 @@
1
+ export type SettledResult<T> = {
2
+ status: 'fulfilled';
3
+ value: T;
4
+ } | {
5
+ status: 'rejected';
6
+ reason: unknown;
7
+ };
8
+ /**
9
+ * Promise.allSettled polyfill — the RN/Hermes target for this app doesn't
10
+ * ship it, so a rejection would otherwise short-circuit Promise.all.
11
+ */
12
+ export declare const allSettled: <T extends readonly unknown[]>(promises: readonly [...T]) => Promise<{ [K in keyof T]: SettledResult<Awaited<T[K]>>; }>;
13
+ //# sourceMappingURL=promise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promise.d.ts","sourceRoot":"","sources":["../../../../src/utils/promise.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,CAAC,CAAC,IACvB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACjC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,SAAS,OAAO,EAAE,EACrD,UAAU,SAAS,CAAC,GAAG,CAAC,CAAC,KACxB,OAAO,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAE,CAOK,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function opacityToSolid(foregroundColor: string, backgroundColor: string, alpha: number): string;
2
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../../../src/utils/ui.ts"],"names":[],"mappings":"AAUA,wBAAgB,cAAc,CAC5B,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,UASd"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@droppii-org/chat-mobile",
3
- "version": "0.2.25",
3
+ "version": "0.2.27",
4
4
  "description": "Droppii chat mobile",
5
5
  "keywords": [
6
6
  "react-native",
@@ -85,6 +85,7 @@
85
85
  "@eslint/js": "^10.0.1",
86
86
  "@growthbook/growthbook-react": "*",
87
87
  "@jest/globals": "^30.0.0",
88
+ "@react-native-clipboard/clipboard": "^1.16.3",
88
89
  "@react-native-documents/picker": "^12.0.1",
89
90
  "@react-native/babel-preset": "0.85.0",
90
91
  "@react-native/eslint-config": "0.85.0",
@@ -136,6 +137,7 @@
136
137
  },
137
138
  "peerDependencies": {
138
139
  "@droppii/libs": "*",
140
+ "@react-native-clipboard/clipboard": "*",
139
141
  "@react-native-documents/picker": "*",
140
142
  "@tanstack/react-query": "*",
141
143
  "react": "*",
@@ -69,11 +69,9 @@ export const InputButtonFlow = memo((props: IInputButtonFlow) => {
69
69
  if (!nodeData) return null;
70
70
 
71
71
  return (
72
- <KContainer.View style={messageStyles.wrapper}>
73
- <KContainer.View style={styles.bubble}>
74
- <KContainer.View style={styles.buttonsContainer}>
75
- {nodeData?.data?.buttons?.map((item) => renderButtonItem(item))}
76
- </KContainer.View>
72
+ <KContainer.View style={styles.bubble}>
73
+ <KContainer.View style={styles.buttonsContainer}>
74
+ {nodeData?.data?.buttons?.map((item) => renderButtonItem(item))}
77
75
  </KContainer.View>
78
76
  </KContainer.View>
79
77
  );
@@ -53,7 +53,6 @@ export const FileMessage = memo(
53
53
  padding={'0.5rem'}
54
54
  style={[
55
55
  styles.wrapper,
56
- messageStyles.wrapper,
57
56
  isOutgoing ? messageStyles.bubbleSent : messageStyles.bubbleReceived,
58
57
  ]}
59
58
  >
@@ -101,7 +101,7 @@ export const ImageMessage = memo(
101
101
  );
102
102
 
103
103
  return (
104
- <KContainer.View style={[messageStyles.wrapper, styles.wrapper]}>
104
+ <KContainer.View style={styles.wrapper}>
105
105
  <KContainer.Touchable
106
106
  onPress={handlePress}
107
107
  style={[
@@ -79,7 +79,7 @@ export const LinkMessage = memo(
79
79
  const timeLabel = formatMessageTime(createdAtTime);
80
80
 
81
81
  return (
82
- <KContainer.View style={styles.wrapper}>
82
+ <>
83
83
  <KContainer.View
84
84
  style={[
85
85
  styles.bubble,
@@ -139,7 +139,7 @@ export const LinkMessage = memo(
139
139
  )}
140
140
  </KContainer.View>
141
141
 
142
- <KContainer.View row alignItems style={{ gap: 4, marginTop: 2 }}>
142
+ <KContainer.View row alignItems style={styles.timeLabel}>
143
143
  {!isOutgoing && timeLabel ? (
144
144
  <KLabel.Text
145
145
  typo="TextXsNormal"
@@ -150,7 +150,7 @@ export const LinkMessage = memo(
150
150
  </KLabel.Text>
151
151
  ) : null}
152
152
  </KContainer.View>
153
- </KContainer.View>
153
+ </>
154
154
  );
155
155
  }
156
156
  );
@@ -191,4 +191,5 @@ const styles = StyleSheet.create({
191
191
  paddingVertical: KSpacingValue['0.5rem'],
192
192
  gap: 2,
193
193
  },
194
+ timeLabel: { gap: 4, marginTop: 2 },
194
195
  });
@@ -17,23 +17,19 @@ export const MergedMessage = memo(
17
17
  );
18
18
 
19
19
  return (
20
- <KContainer.View style={messageStyles.wrapper}>
21
- <KContainer.View
22
- style={[
23
- messageStyles.bubble,
24
- isOutgoing
25
- ? messageStyles.bubbleSent
26
- : messageStyles.bubbleReceived,
27
- ]}
28
- >
29
- {imageMessages.length > 0 && (
30
- <MergedImageGrid
31
- images={imageMessages}
32
- maxDisplay={3}
33
- onMediaPress={onMediaPress}
34
- />
35
- )}
36
- </KContainer.View>
20
+ <KContainer.View
21
+ style={[
22
+ messageStyles.bubble,
23
+ isOutgoing ? messageStyles.bubbleSent : messageStyles.bubbleReceived,
24
+ ]}
25
+ >
26
+ {imageMessages.length > 0 && (
27
+ <MergedImageGrid
28
+ images={imageMessages}
29
+ maxDisplay={3}
30
+ onMediaPress={onMediaPress}
31
+ />
32
+ )}
37
33
  </KContainer.View>
38
34
  );
39
35
  }
@@ -36,4 +36,16 @@ export const messageStyles = StyleSheet.create({
36
36
  bottom: 0,
37
37
  backgroundColor: 'rgba(0, 0, 0, 0.3)',
38
38
  },
39
+ messageRowLeft: {
40
+ width: '100%',
41
+ paddingHorizontal: KSpacingValue['0.75rem'],
42
+ marginBottom: KSpacingValue['0.25rem'],
43
+ alignItems: 'flex-start',
44
+ },
45
+ messageRowRight: {
46
+ width: '100%',
47
+ paddingHorizontal: KSpacingValue['0.75rem'],
48
+ marginBottom: KSpacingValue['0.25rem'],
49
+ alignItems: 'flex-end',
50
+ },
39
51
  });
@@ -5,6 +5,7 @@ import { CHAT_BUBBLE_COLORS } from '../../../screens/chat-detail/constants';
5
5
  import { messageStyles } from '../styles';
6
6
  import { formatMessageTime } from '../types';
7
7
  import type { BaseLegendMessageProps } from '../types';
8
+ import { StyleSheet } from 'react-native';
8
9
  export const TextMessage = memo(
9
10
  ({ message, isOutgoing, createdAtTime }: BaseLegendMessageProps) => {
10
11
  const messageText = getMessageText(message);
@@ -15,7 +16,7 @@ export const TextMessage = memo(
15
16
  }
16
17
 
17
18
  return (
18
- <KContainer.View style={messageStyles.wrapper}>
19
+ <>
19
20
  <KContainer.View
20
21
  style={[
21
22
  messageStyles.bubble,
@@ -29,7 +30,7 @@ export const TextMessage = memo(
29
30
  </KLabel.Text>
30
31
  </KContainer.View>
31
32
 
32
- <KContainer.View row alignItems style={{ gap: 4, marginTop: 2 }}>
33
+ <KContainer.View row alignItems style={styles.timeLabel}>
33
34
  {!isOutgoing && timeLabel ? (
34
35
  <KLabel.Text
35
36
  typo="TextXsNormal"
@@ -40,9 +41,13 @@ export const TextMessage = memo(
40
41
  </KLabel.Text>
41
42
  ) : null}
42
43
  </KContainer.View>
43
- </KContainer.View>
44
+ </>
44
45
  );
45
46
  }
46
47
  );
47
48
 
48
49
  TextMessage.displayName = 'TextMessage';
50
+
51
+ const styles = StyleSheet.create({
52
+ timeLabel: { gap: 4, marginTop: 2 },
53
+ });
@@ -29,14 +29,12 @@ export const VideoMessage = memo(
29
29
 
30
30
  if (!videoUrl) {
31
31
  return (
32
- <KContainer.View style={messageStyles.wrapper}>
33
- <KContainer.View
34
- style={[messageStyles.bubble, messageStyles.videoPlaceholder]}
35
- >
36
- <KLabel.Text typo="TextSmNormal" color={CHAT_BUBBLE_COLORS.text}>
37
- 📹 [Video unavailable]
38
- </KLabel.Text>
39
- </KContainer.View>
32
+ <KContainer.View
33
+ style={[messageStyles.bubble, messageStyles.videoPlaceholder]}
34
+ >
35
+ <KLabel.Text typo="TextSmNormal" color={CHAT_BUBBLE_COLORS.text}>
36
+ 📹 [Video unavailable]
37
+ </KLabel.Text>
40
38
  </KContainer.View>
41
39
  );
42
40
  }
@@ -46,7 +44,7 @@ export const VideoMessage = memo(
46
44
  );
47
45
 
48
46
  return (
49
- <KContainer.View style={messageStyles.wrapper}>
47
+ <>
50
48
  <KContainer.Touchable
51
49
  onPress={handlePress}
52
50
  style={[
@@ -82,7 +80,7 @@ export const VideoMessage = memo(
82
80
  </KContainer.View>
83
81
  )}
84
82
  </KContainer.Touchable>
85
- </KContainer.View>
83
+ </>
86
84
  );
87
85
  }
88
86
  );
package/src/core/index.ts CHANGED
@@ -3,6 +3,9 @@ import type { InitOptions } from '@droppii/openim-rn-client-sdk';
3
3
  import { initBaseUrl } from '../config/configuration';
4
4
  import { useUserListener } from './useUserListener';
5
5
  import { useChatListener } from './useChatListener';
6
+ import { useBackgroundStatusSync } from './notification/useBackgroundStatusSync';
7
+
8
+ export * from './notification';
6
9
 
7
10
  export interface InitChatSdkOptions extends InitOptions {
8
11
  /**
@@ -31,4 +34,5 @@ export const initChatSdk = (options: InitChatSdkOptions) => {
31
34
  export const useChatSdk = () => {
32
35
  useUserListener();
33
36
  useChatListener();
37
+ useBackgroundStatusSync();
34
38
  };
@@ -0,0 +1,22 @@
1
+ import OpenIMSDK from '@droppii/openim-rn-client-sdk';
2
+ import type { AppStateStatus } from 'react-native';
3
+
4
+ export const syncAppBackgroundStatus = (
5
+ isBackground: boolean
6
+ ): Promise<void> => {
7
+ return OpenIMSDK.setAppBackgroundStatus(isBackground).then(() => undefined);
8
+ };
9
+
10
+ const defaultResolver = (state: AppStateStatus): boolean => state !== 'active';
11
+
12
+ let _resolver: (state: AppStateStatus) => boolean = defaultResolver;
13
+
14
+ export const registerBackgroundStatusResolver = (
15
+ resolver: (state: AppStateStatus) => boolean
16
+ ): void => {
17
+ _resolver = resolver;
18
+ };
19
+
20
+ /** @internal used by useBackgroundStatusSync, not part of the public surface */
21
+ export const resolveIsBackground = (state: AppStateStatus): boolean =>
22
+ _resolver(state);
@@ -0,0 +1,5 @@
1
+ export { registerPushToken, unregisterPushToken } from './pushToken';
2
+ export {
3
+ syncAppBackgroundStatus,
4
+ registerBackgroundStatusResolver,
5
+ } from './backgroundStatus';
@@ -0,0 +1,24 @@
1
+ import OpenIMSDK from '@droppii/openim-rn-client-sdk';
2
+
3
+ /**
4
+ * Default TTL (seconds — confirmed unit per docs.openim.io/sdks/api/third/updatefcmtoken).
5
+ * Not an OpenIM-mandated value, just a reasonable default (90 days).
6
+ */
7
+ export const DEFAULT_PUSH_TOKEN_EXPIRE_SECONDS = 7776000;
8
+
9
+ export const registerPushToken = (
10
+ fcmToken: string,
11
+ expireTime: number = DEFAULT_PUSH_TOKEN_EXPIRE_SECONDS
12
+ ): Promise<void> => {
13
+ return OpenIMSDK.updateFcmToken(fcmToken, expireTime);
14
+ };
15
+
16
+ /**
17
+ * Clears the token on logout. OpenIM has no documented dedicated "clear" API
18
+ * (docs.openim.io only documents setting a token) — this mirrors Firebase's
19
+ * empty-token convention. UNVERIFIED with the OpenIM/backend team; confirm
20
+ * before relying on this in production.
21
+ */
22
+ export const unregisterPushToken = (): Promise<void> => {
23
+ return OpenIMSDK.updateFcmToken('', 0);
24
+ };
@@ -0,0 +1,18 @@
1
+ import { useEffect } from 'react';
2
+ import { AppState } from 'react-native';
3
+ import {
4
+ syncAppBackgroundStatus,
5
+ resolveIsBackground,
6
+ } from './backgroundStatus';
7
+
8
+ export const useBackgroundStatusSync = () => {
9
+ useEffect(() => {
10
+ const sub = AppState.addEventListener('change', (state) => {
11
+ syncAppBackgroundStatus(resolveIsBackground(state));
12
+ });
13
+
14
+ return () => {
15
+ sub.remove();
16
+ };
17
+ }, []);
18
+ };
@@ -13,6 +13,7 @@ import {
13
13
  import { useMessageStore } from '../store/message';
14
14
  import { useUserStore } from '../store/user';
15
15
  import { useChatContext } from '../context';
16
+ import { allSettled } from '../utils/promise';
16
17
 
17
18
  type UseChatMessagesOptions = {
18
19
  conversationId: string;
@@ -54,7 +55,7 @@ export function useChatMessages({
54
55
  try {
55
56
  // Fetch userId and history independently so an offline SDK state
56
57
  // doesn't block reading local SQLite history.
57
- const [historyResult, userIdResult] = await Promise.allSettled([
58
+ const [historyResult, userIdResult] = await allSettled([
58
59
  ChatMessageAPI.fetchHistoryMessages(conversationId, {
59
60
  count: pageSize,
60
61
  applicationType,
package/src/index.tsx CHANGED
@@ -52,5 +52,6 @@ export type {
52
52
  } from './screens/chat-detail';
53
53
 
54
54
  export type { PeerType } from '@droppii/openim-rn-client-sdk';
55
+ export { LoginStatus } from '@droppii/openim-rn-client-sdk';
55
56
 
56
57
  export { registerUIUtils, UIUtils } from './utils/UIUtils';
@@ -24,6 +24,9 @@ import type { ChatDetailProps } from './types';
24
24
  import { ChatDetailProvider } from '../../context/ChatDetailContext';
25
25
  import { normalizeUrl } from '../../utils/url';
26
26
  // import { ChatMessageAPI } from '../../services/message';
27
+ import { MessageToolboxOverlay } from './messageToolbox/MessageToolboxOverlay';
28
+ import type { MeasuredRect, MessageToolboxRef } from './messageToolbox/types';
29
+ import type { DMessageItem } from '../../types/chat';
27
30
 
28
31
  const ChatDetail = memo(
29
32
  ({
@@ -45,6 +48,7 @@ const ChatDetail = memo(
45
48
  }: ChatDetailProps) => {
46
49
  const navigation = useNavigation();
47
50
  const mediaViewerRef = useRef<MediaViewerModalHandle>(null);
51
+ const messageToolboxRef = useRef<MessageToolboxRef>(null);
48
52
  const conversation = useConversation(conversationId);
49
53
 
50
54
  const handleBackDefault = useCallback(() => {
@@ -111,6 +115,13 @@ const ChatDetail = memo(
111
115
  [onPressUrl]
112
116
  );
113
117
 
118
+ const handleMessageLongPress = useCallback(
119
+ (message: DMessageItem, rect: MeasuredRect) => {
120
+ messageToolboxRef.current?.show(message, rect);
121
+ },
122
+ []
123
+ );
124
+
114
125
  return (
115
126
  <ChatDetailProvider>
116
127
  <KContainer.Page flex edges={['bottom']}>
@@ -143,12 +154,18 @@ const ChatDetail = memo(
143
154
  hasMoreEarlier={hasMoreEarlier}
144
155
  onMediaPress={handleMediaPress}
145
156
  onPressUrl={handlePressUrl}
157
+ onLongPress={handleMessageLongPress}
146
158
  />
147
159
 
148
160
  <ChatComposer isEmptyMessage={messages?.length === 0} />
149
161
  </KeyboardAvoidingView>
150
162
 
151
163
  <MediaViewerModal ref={mediaViewerRef} />
164
+ <MessageToolboxOverlay
165
+ ref={messageToolboxRef}
166
+ currentUserId={currentUserId}
167
+ customMessageItemFactory={customMessageItemFactory}
168
+ />
152
169
  </KContainer.Page>
153
170
  </ChatDetailProvider>
154
171
  );