@ethora/chat-component-rn 26.7.3 → 26.7.5

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 (143) hide show
  1. package/CHANGELOG.md +0 -9
  2. package/README.md +0 -22
  3. package/lib/commonjs/assets/icons.js +2 -2
  4. package/lib/commonjs/assets/icons.js.map +1 -1
  5. package/lib/commonjs/components/MainComponents/ChatRoom.js +10 -10
  6. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/MessageList.js +22 -5
  8. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +8 -9
  10. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  11. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +37 -110
  12. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  13. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +14 -16
  14. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  15. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js +1 -2
  16. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  17. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js +0 -8
  18. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  19. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js +21 -7
  20. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  21. package/lib/commonjs/components/styled/SendInput.js +10 -0
  22. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  23. package/lib/commonjs/context/xmppProvider.js +35 -6
  24. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  25. package/lib/commonjs/helpers/updateMessagesTillLast.js +40 -12
  26. package/lib/commonjs/helpers/updateMessagesTillLast.js.map +1 -1
  27. package/lib/commonjs/hooks/useChatRoomFocus.js +9 -3
  28. package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -1
  29. package/lib/commonjs/hooks/useLogout.js +5 -0
  30. package/lib/commonjs/hooks/useLogout.js.map +1 -1
  31. package/lib/commonjs/hooks/useSendMessage.js +50 -23
  32. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  33. package/lib/commonjs/main.js +0 -6
  34. package/lib/commonjs/main.js.map +1 -1
  35. package/lib/commonjs/networking/outboundQueue.js +18 -0
  36. package/lib/commonjs/networking/outboundQueue.js.map +1 -1
  37. package/lib/commonjs/networking/stanzaHandlers.js +10 -1
  38. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  39. package/lib/commonjs/networking/xmppClient.js +107 -7
  40. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  41. package/lib/commonjs/roomStore/roomsSlice.js +22 -3
  42. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  43. package/lib/module/assets/icons.js +1 -1
  44. package/lib/module/assets/icons.js.map +1 -1
  45. package/lib/module/components/MainComponents/ChatRoom.js +10 -10
  46. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  47. package/lib/module/components/MainComponents/MessageList.js +23 -6
  48. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  49. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +8 -9
  50. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  51. package/lib/module/components/Menu/HeaderRoomListMenu.js +38 -110
  52. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  53. package/lib/module/components/Modals/AttachSheet/AttachSheet.js +14 -16
  54. package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  55. package/lib/module/components/Modals/NewChatModal/ModalContent.js +1 -2
  56. package/lib/module/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  57. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js +0 -8
  58. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  59. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js +23 -9
  60. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  61. package/lib/module/components/styled/SendInput.js +11 -1
  62. package/lib/module/components/styled/SendInput.js.map +1 -1
  63. package/lib/module/context/xmppProvider.js +35 -6
  64. package/lib/module/context/xmppProvider.js.map +1 -1
  65. package/lib/module/helpers/updateMessagesTillLast.js +41 -13
  66. package/lib/module/helpers/updateMessagesTillLast.js.map +1 -1
  67. package/lib/module/hooks/useChatRoomFocus.js +9 -3
  68. package/lib/module/hooks/useChatRoomFocus.js.map +1 -1
  69. package/lib/module/hooks/useLogout.js +5 -0
  70. package/lib/module/hooks/useLogout.js.map +1 -1
  71. package/lib/module/hooks/useSendMessage.js +51 -24
  72. package/lib/module/hooks/useSendMessage.js.map +1 -1
  73. package/lib/module/main.js +1 -1
  74. package/lib/module/main.js.map +1 -1
  75. package/lib/module/networking/outboundQueue.js +17 -0
  76. package/lib/module/networking/outboundQueue.js.map +1 -1
  77. package/lib/module/networking/stanzaHandlers.js +10 -1
  78. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  79. package/lib/module/networking/xmppClient.js +107 -7
  80. package/lib/module/networking/xmppClient.js.map +1 -1
  81. package/lib/module/roomStore/roomsSlice.js +20 -2
  82. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  83. package/lib/typescript/assets/icons.d.ts +0 -4
  84. package/lib/typescript/assets/icons.d.ts.map +1 -1
  85. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  86. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  87. package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
  88. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +0 -3
  89. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  90. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
  91. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts +2 -4
  92. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts.map +1 -1
  93. package/lib/typescript/components/Modals/NewChatModal/UpdNewChatModal.d.ts.map +1 -1
  94. package/lib/typescript/components/Modals/UserProfileModal/EditUserModal.d.ts.map +1 -1
  95. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  96. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  97. package/lib/typescript/helpers/updateMessagesTillLast.d.ts.map +1 -1
  98. package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -1
  99. package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
  100. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  101. package/lib/typescript/main.d.ts +1 -1
  102. package/lib/typescript/main.d.ts.map +1 -1
  103. package/lib/typescript/networking/outboundQueue.d.ts +16 -0
  104. package/lib/typescript/networking/outboundQueue.d.ts.map +1 -1
  105. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  106. package/lib/typescript/networking/xmppClient.d.ts +33 -1
  107. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  108. package/lib/typescript/roomStore/roomsSlice.d.ts +18 -1
  109. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  110. package/lib/typescript/types/models/room.model.d.ts +15 -0
  111. package/lib/typescript/types/models/room.model.d.ts.map +1 -1
  112. package/lib/typescript/types/types.d.ts +15 -12
  113. package/lib/typescript/types/types.d.ts.map +1 -1
  114. package/package.json +1 -1
  115. package/src/assets/icons.tsx +0 -19
  116. package/src/components/MainComponents/ChatRoom.tsx +13 -9
  117. package/src/components/MainComponents/MessageList.tsx +23 -6
  118. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +9 -16
  119. package/src/components/Menu/HeaderRoomListMenu.tsx +11 -105
  120. package/src/components/Modals/AttachSheet/AttachSheet.tsx +14 -16
  121. package/src/components/Modals/NewChatModal/ModalContent.tsx +3 -6
  122. package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +1 -12
  123. package/src/components/Modals/UserProfileModal/EditUserModal.tsx +25 -9
  124. package/src/components/styled/SendInput.tsx +10 -0
  125. package/src/context/xmppProvider.tsx +41 -8
  126. package/src/helpers/updateMessagesTillLast.tsx +42 -17
  127. package/src/hooks/useChatRoomFocus.ts +11 -3
  128. package/src/hooks/useLogout.tsx +7 -0
  129. package/src/hooks/useSendMessage.tsx +60 -24
  130. package/src/main.ts +1 -1
  131. package/src/networking/outboundQueue.ts +29 -0
  132. package/src/networking/stanzaHandlers.ts +9 -1
  133. package/src/networking/xmppClient.ts +118 -7
  134. package/src/roomStore/roomsSlice.ts +20 -2
  135. package/src/types/models/room.model.ts +15 -0
  136. package/src/types/types.ts +15 -14
  137. package/lib/commonjs/helpers/pickImageAsset.js +0 -68
  138. package/lib/commonjs/helpers/pickImageAsset.js.map +0 -1
  139. package/lib/module/helpers/pickImageAsset.js +0 -63
  140. package/lib/module/helpers/pickImageAsset.js.map +0 -1
  141. package/lib/typescript/helpers/pickImageAsset.d.ts +0 -27
  142. package/lib/typescript/helpers/pickImageAsset.d.ts.map +0 -1
  143. package/src/helpers/pickImageAsset.ts +0 -68
@@ -317,8 +317,6 @@ const reducers = {
317
317
  : [];
318
318
  state.rooms[roomData.jid] = {
319
319
  ...roomData,
320
- icon: roomData.icon !== undefined ? roomData.icon : existing?.icon,
321
- roomBg: roomData.roomBg !== undefined ? roomData.roomBg : existing?.roomBg,
322
320
  messages:
323
321
  existingMessages.length > 0 ? existingMessages : incomingMessages,
324
322
  lastViewedTimestamp: lastViewed,
@@ -545,6 +543,25 @@ const reducers = {
545
543
  ) => {
546
544
  state.isUnreadSyncing = action.payload;
547
545
  },
546
+ /**
547
+ * Records how far the user has actually read in a room: the timestamp
548
+ * of the newest message they had reached when they scrolled away from
549
+ * the bottom, or `null` while they are at the bottom.
550
+ *
551
+ * Written only by MessageList as the user scrolls. Deliberately does
552
+ * NOT touch `unreadMessages` or `lastViewedTimestamp` — it only tells
553
+ * the various "mark this room read" paths what value to stamp instead
554
+ * of `Date.now()`. Customer-reported #33.
555
+ */
556
+ setReadBoundary: (
557
+ state: WritableDraft<RoomMessagesState>,
558
+ action: PayloadAction<{ chatJID: string; boundaryTs: number | null }>
559
+ ) => {
560
+ const { chatJID, boundaryTs } = action.payload;
561
+ if (state.rooms[chatJID]) {
562
+ state.rooms[chatJID].readBoundaryTs = boundaryTs;
563
+ }
564
+ },
548
565
  setLastViewedTimestamp: (
549
566
  state: WritableDraft<RoomMessagesState>,
550
567
  action: PayloadAction<{ chatJID: string; timestamp: number }>
@@ -901,6 +918,7 @@ export const {
901
918
  setIsLoading,
902
919
  setUnreadSyncing,
903
920
  setLastViewedTimestamp,
921
+ setReadBoundary,
904
922
  applyPrivateStoreMarkers,
905
923
  setRoomNoMessages,
906
924
  setCurrentRoom,
@@ -50,6 +50,21 @@ export interface IRoom {
50
50
  composingList?: string[];
51
51
  lastViewedTimestamp?: number;
52
52
  unreadMessages?: number;
53
+ /**
54
+ * Timestamp of the newest message the user had actually reached when
55
+ * they scrolled away from the bottom of this room, or null/undefined
56
+ * while they are at the bottom (everything on screen is read).
57
+ *
58
+ * Lives in the store rather than in ChatRoom's local state because
59
+ * several code paths outside the component mark a room read — the
60
+ * AppState background handler, the `isVisible` consumer signal, the
61
+ * visible-room auto-advance, `useChatRoomFocus` — and all of them must
62
+ * stamp what the user actually saw instead of `Date.now()`. Stamping
63
+ * "now" while they are scrolled up silently destroys unread messages,
64
+ * and because those paths also flush to the server-side private store
65
+ * the loss survives an app restart. Customer-reported #33.
66
+ */
67
+ readBoundaryTs?: number | null;
53
68
  noMessages?: boolean;
54
69
  role?: string;
55
70
 
@@ -33,6 +33,21 @@ export interface IRoom {
33
33
  composingList?: string[];
34
34
  lastViewedTimestamp?: number;
35
35
  unreadMessages?: number;
36
+ /**
37
+ * Timestamp of the newest message the user had actually reached when
38
+ * they scrolled away from the bottom of this room; null/undefined while
39
+ * they are at the bottom (everything on screen is read).
40
+ *
41
+ * Written only by MessageList as the user scrolls. Every path that marks
42
+ * a room read must prefer this over `Date.now()` — the AppState
43
+ * background handler, the `isVisible` consumer signal, the visible-room
44
+ * auto-advance, `useChatRoomFocus` and logout all flush to the
45
+ * server-side private store, so stamping "now" while the user is
46
+ * scrolled up destroys unread messages permanently (survives an app
47
+ * restart, because the bad marker comes back from the server).
48
+ * Customer-reported #33.
49
+ */
50
+ readBoundaryTs?: number | null;
36
51
  noMessages?: boolean;
37
52
  role?: string;
38
53
  createdAt?: string | number | Date;
@@ -454,20 +469,6 @@ export interface IConfig {
454
469
  loginFunction: () => Promise<User | null>;
455
470
  };
456
471
  defaultLogin?: boolean;
457
- logout?: {
458
- enabled: boolean;
459
- label?: string;
460
- confirm?:
461
- | boolean
462
- | {
463
- title?: string;
464
- message?: string;
465
- confirmText?: string;
466
- cancelText?: string;
467
- };
468
- onBeforeLogout?: () => Promise<boolean | void> | boolean | void;
469
- onAfterLogout?: () => Promise<void> | void;
470
- };
471
472
  refreshTokens?: {
472
473
  enabled: boolean;
473
474
  /**
@@ -1,68 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.pickImageAsset = void 0;
7
- var _reactNative = require("react-native");
8
- var ImagePicker = _interopRequireWildcard(require("expo-image-picker"));
9
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
10
- /**
11
- * A picked image in the shape React Native's FormData understands.
12
- *
13
- * NOT a web `File`: RN streams a multipart part straight from a `file://`
14
- * uri and has no usable Blob/File/atob path. Screens ported from the web
15
- * client used to carry base64 -> Blob -> File helpers that could never
16
- * have run here.
17
- */
18
-
19
- /**
20
- * Ask for library permission, open the picker, and normalise the result.
21
- *
22
- * Returns `null` for every non-error outcome — permission refused, user
23
- * cancelled — so call sites can simply keep their current value.
24
- *
25
- * Exists because the avatar pickers are wired to `onPress`, which hands
26
- * the callback a SyntheticEvent. Storing that event as "the image" (what
27
- * two screens used to do) rendered a pooled event as an <Image source>
28
- * and then crashed with "Property is not configurable" when React tried
29
- * to release it — on top of never letting the user pick anything.
30
- */
31
- const pickImageAsset = async () => {
32
- try {
33
- // expo-image-picker owns the permission prompt internally and
34
- // returns a `granted` flag.
35
- const perm = await ImagePicker.requestMediaLibraryPermissionsAsync();
36
- if (!perm.granted) {
37
- _reactNative.Alert.alert('Permission required', 'Photo library permission is needed to select images.', [{
38
- text: 'Cancel',
39
- style: 'cancel'
40
- }, {
41
- text: 'Open Settings',
42
- onPress: () => _reactNative.Linking.openSettings()
43
- }]);
44
- return null;
45
- }
46
- const result = await ImagePicker.launchImageLibraryAsync({
47
- mediaTypes: ['images'],
48
- allowsEditing: true,
49
- aspect: [1, 1],
50
- quality: 0.8
51
- });
52
- if (result.canceled || !result.assets?.[0]) {
53
- return null;
54
- }
55
- const asset = result.assets[0];
56
- const originalName = asset.fileName || asset.uri.split('/').pop();
57
- return {
58
- uri: asset.uri,
59
- type: asset.mimeType || 'image/jpeg',
60
- name: originalName || `image_${Date.now()}.jpg`
61
- };
62
- } catch (error) {
63
- console.error('Failed to pick an image:', error);
64
- return null;
65
- }
66
- };
67
- exports.pickImageAsset = pickImageAsset;
68
- //# sourceMappingURL=pickImageAsset.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_reactNative","require","ImagePicker","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","pickImageAsset","perm","requestMediaLibraryPermissionsAsync","granted","Alert","alert","text","style","onPress","Linking","openSettings","result","launchImageLibraryAsync","mediaTypes","allowsEditing","aspect","quality","canceled","assets","asset","originalName","fileName","uri","split","pop","type","mimeType","name","Date","now","error","console","exports"],"sourceRoot":"../../../src","sources":["helpers/pickImageAsset.ts"],"mappings":"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","ignoreList":[]}
@@ -1,63 +0,0 @@
1
- "use strict";
2
-
3
- import { Alert, Linking } from 'react-native';
4
- import * as ImagePicker from 'expo-image-picker';
5
-
6
- /**
7
- * A picked image in the shape React Native's FormData understands.
8
- *
9
- * NOT a web `File`: RN streams a multipart part straight from a `file://`
10
- * uri and has no usable Blob/File/atob path. Screens ported from the web
11
- * client used to carry base64 -> Blob -> File helpers that could never
12
- * have run here.
13
- */
14
-
15
- /**
16
- * Ask for library permission, open the picker, and normalise the result.
17
- *
18
- * Returns `null` for every non-error outcome — permission refused, user
19
- * cancelled — so call sites can simply keep their current value.
20
- *
21
- * Exists because the avatar pickers are wired to `onPress`, which hands
22
- * the callback a SyntheticEvent. Storing that event as "the image" (what
23
- * two screens used to do) rendered a pooled event as an <Image source>
24
- * and then crashed with "Property is not configurable" when React tried
25
- * to release it — on top of never letting the user pick anything.
26
- */
27
- export const pickImageAsset = async () => {
28
- try {
29
- // expo-image-picker owns the permission prompt internally and
30
- // returns a `granted` flag.
31
- const perm = await ImagePicker.requestMediaLibraryPermissionsAsync();
32
- if (!perm.granted) {
33
- Alert.alert('Permission required', 'Photo library permission is needed to select images.', [{
34
- text: 'Cancel',
35
- style: 'cancel'
36
- }, {
37
- text: 'Open Settings',
38
- onPress: () => Linking.openSettings()
39
- }]);
40
- return null;
41
- }
42
- const result = await ImagePicker.launchImageLibraryAsync({
43
- mediaTypes: ['images'],
44
- allowsEditing: true,
45
- aspect: [1, 1],
46
- quality: 0.8
47
- });
48
- if (result.canceled || !result.assets?.[0]) {
49
- return null;
50
- }
51
- const asset = result.assets[0];
52
- const originalName = asset.fileName || asset.uri.split('/').pop();
53
- return {
54
- uri: asset.uri,
55
- type: asset.mimeType || 'image/jpeg',
56
- name: originalName || `image_${Date.now()}.jpg`
57
- };
58
- } catch (error) {
59
- console.error('Failed to pick an image:', error);
60
- return null;
61
- }
62
- };
63
- //# sourceMappingURL=pickImageAsset.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["Alert","Linking","ImagePicker","pickImageAsset","perm","requestMediaLibraryPermissionsAsync","granted","alert","text","style","onPress","openSettings","result","launchImageLibraryAsync","mediaTypes","allowsEditing","aspect","quality","canceled","assets","asset","originalName","fileName","uri","split","pop","type","mimeType","name","Date","now","error","console"],"sourceRoot":"../../../src","sources":["helpers/pickImageAsset.ts"],"mappings":";;AAAA,SAASA,KAAK,EAAEC,OAAO,QAAQ,cAAc;AAC7C,OAAO,KAAKC,WAAW,MAAM,mBAAmB;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,cAAc,GAAG,MAAAA,CAAA,KAAyC;EACrE,IAAI;IACF;IACA;IACA,MAAMC,IAAI,GAAG,MAAMF,WAAW,CAACG,mCAAmC,CAAC,CAAC;IACpE,IAAI,CAACD,IAAI,CAACE,OAAO,EAAE;MACjBN,KAAK,CAACO,KAAK,CACT,qBAAqB,EACrB,sDAAsD,EACtD,CACE;QAAEC,IAAI,EAAE,QAAQ;QAAEC,KAAK,EAAE;MAAS,CAAC,EACnC;QAAED,IAAI,EAAE,eAAe;QAAEE,OAAO,EAAEA,CAAA,KAAMT,OAAO,CAACU,YAAY,CAAC;MAAE,CAAC,CAEpE,CAAC;MACD,OAAO,IAAI;IACb;IAEA,MAAMC,MAAM,GAAG,MAAMV,WAAW,CAACW,uBAAuB,CAAC;MACvDC,UAAU,EAAE,CAAC,QAAQ,CAAC;MACtBC,aAAa,EAAE,IAAI;MACnBC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;MACdC,OAAO,EAAE;IACX,CAAC,CAAC;IACF,IAAIL,MAAM,CAACM,QAAQ,IAAI,CAACN,MAAM,CAACO,MAAM,GAAG,CAAC,CAAC,EAAE;MAC1C,OAAO,IAAI;IACb;IAEA,MAAMC,KAAK,GAAGR,MAAM,CAACO,MAAM,CAAC,CAAC,CAAC;IAC9B,MAAME,YAAY,GAAGD,KAAK,CAACE,QAAQ,IAAIF,KAAK,CAACG,GAAG,CAACC,KAAK,CAAC,GAAG,CAAC,CAACC,GAAG,CAAC,CAAC;IACjE,OAAO;MACLF,GAAG,EAAEH,KAAK,CAACG,GAAG;MACdG,IAAI,EAAEN,KAAK,CAACO,QAAQ,IAAI,YAAY;MACpCC,IAAI,EAAEP,YAAY,IAAI,SAASQ,IAAI,CAACC,GAAG,CAAC,CAAC;IAC3C,CAAC;EACH,CAAC,CAAC,OAAOC,KAAK,EAAE;IACdC,OAAO,CAACD,KAAK,CAAC,0BAA0B,EAAEA,KAAK,CAAC;IAChD,OAAO,IAAI;EACb;AACF,CAAC","ignoreList":[]}
@@ -1,27 +0,0 @@
1
- /**
2
- * A picked image in the shape React Native's FormData understands.
3
- *
4
- * NOT a web `File`: RN streams a multipart part straight from a `file://`
5
- * uri and has no usable Blob/File/atob path. Screens ported from the web
6
- * client used to carry base64 -> Blob -> File helpers that could never
7
- * have run here.
8
- */
9
- export interface PickedImage {
10
- uri: string;
11
- type: string;
12
- name: string;
13
- }
14
- /**
15
- * Ask for library permission, open the picker, and normalise the result.
16
- *
17
- * Returns `null` for every non-error outcome — permission refused, user
18
- * cancelled — so call sites can simply keep their current value.
19
- *
20
- * Exists because the avatar pickers are wired to `onPress`, which hands
21
- * the callback a SyntheticEvent. Storing that event as "the image" (what
22
- * two screens used to do) rendered a pooled event as an <Image source>
23
- * and then crashed with "Property is not configurable" when React tried
24
- * to release it — on top of never letting the user pick anything.
25
- */
26
- export declare const pickImageAsset: () => Promise<PickedImage | null>;
27
- //# sourceMappingURL=pickImageAsset.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pickImageAsset.d.ts","sourceRoot":"","sources":["../../../src/helpers/pickImageAsset.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,QAAa,OAAO,CAAC,WAAW,GAAG,IAAI,CAsCjE,CAAC"}
@@ -1,68 +0,0 @@
1
- import { Alert, Linking } from 'react-native';
2
- import * as ImagePicker from 'expo-image-picker';
3
-
4
- /**
5
- * A picked image in the shape React Native's FormData understands.
6
- *
7
- * NOT a web `File`: RN streams a multipart part straight from a `file://`
8
- * uri and has no usable Blob/File/atob path. Screens ported from the web
9
- * client used to carry base64 -> Blob -> File helpers that could never
10
- * have run here.
11
- */
12
- export interface PickedImage {
13
- uri: string;
14
- type: string;
15
- name: string;
16
- }
17
-
18
- /**
19
- * Ask for library permission, open the picker, and normalise the result.
20
- *
21
- * Returns `null` for every non-error outcome — permission refused, user
22
- * cancelled — so call sites can simply keep their current value.
23
- *
24
- * Exists because the avatar pickers are wired to `onPress`, which hands
25
- * the callback a SyntheticEvent. Storing that event as "the image" (what
26
- * two screens used to do) rendered a pooled event as an <Image source>
27
- * and then crashed with "Property is not configurable" when React tried
28
- * to release it — on top of never letting the user pick anything.
29
- */
30
- export const pickImageAsset = async (): Promise<PickedImage | null> => {
31
- try {
32
- // expo-image-picker owns the permission prompt internally and
33
- // returns a `granted` flag.
34
- const perm = await ImagePicker.requestMediaLibraryPermissionsAsync();
35
- if (!perm.granted) {
36
- Alert.alert(
37
- 'Permission required',
38
- 'Photo library permission is needed to select images.',
39
- [
40
- { text: 'Cancel', style: 'cancel' },
41
- { text: 'Open Settings', onPress: () => Linking.openSettings() },
42
- ]
43
- );
44
- return null;
45
- }
46
-
47
- const result = await ImagePicker.launchImageLibraryAsync({
48
- mediaTypes: ['images'],
49
- allowsEditing: true,
50
- aspect: [1, 1],
51
- quality: 0.8,
52
- });
53
- if (result.canceled || !result.assets?.[0]) {
54
- return null;
55
- }
56
-
57
- const asset = result.assets[0];
58
- const originalName = asset.fileName || asset.uri.split('/').pop();
59
- return {
60
- uri: asset.uri,
61
- type: asset.mimeType || 'image/jpeg',
62
- name: originalName || `image_${Date.now()}.jpg`,
63
- };
64
- } catch (error) {
65
- console.error('Failed to pick an image:', error);
66
- return null;
67
- }
68
- };