@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.
- package/CHANGELOG.md +0 -9
- package/README.md +0 -22
- package/lib/commonjs/assets/icons.js +2 -2
- package/lib/commonjs/assets/icons.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +10 -10
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +22 -5
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +8 -9
- package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +37 -110
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +14 -16
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js +1 -2
- package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js +0 -8
- package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js +21 -7
- package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +10 -0
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +35 -6
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/updateMessagesTillLast.js +40 -12
- package/lib/commonjs/helpers/updateMessagesTillLast.js.map +1 -1
- package/lib/commonjs/hooks/useChatRoomFocus.js +9 -3
- package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -1
- package/lib/commonjs/hooks/useLogout.js +5 -0
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +50 -23
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/main.js +0 -6
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/networking/outboundQueue.js +18 -0
- package/lib/commonjs/networking/outboundQueue.js.map +1 -1
- package/lib/commonjs/networking/stanzaHandlers.js +10 -1
- package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +107 -7
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +22 -3
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/assets/icons.js +1 -1
- package/lib/module/assets/icons.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +10 -10
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +23 -6
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +8 -9
- package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
- package/lib/module/components/Menu/HeaderRoomListMenu.js +38 -110
- package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js +14 -16
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/ModalContent.js +1 -2
- package/lib/module/components/Modals/NewChatModal/ModalContent.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js +0 -8
- package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/EditUserModal.js +23 -9
- package/lib/module/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +11 -1
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/context/xmppProvider.js +35 -6
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/updateMessagesTillLast.js +41 -13
- package/lib/module/helpers/updateMessagesTillLast.js.map +1 -1
- package/lib/module/hooks/useChatRoomFocus.js +9 -3
- package/lib/module/hooks/useChatRoomFocus.js.map +1 -1
- package/lib/module/hooks/useLogout.js +5 -0
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +51 -24
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/main.js +1 -1
- package/lib/module/main.js.map +1 -1
- package/lib/module/networking/outboundQueue.js +17 -0
- package/lib/module/networking/outboundQueue.js.map +1 -1
- package/lib/module/networking/stanzaHandlers.js +10 -1
- package/lib/module/networking/stanzaHandlers.js.map +1 -1
- package/lib/module/networking/xmppClient.js +107 -7
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +20 -2
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/typescript/assets/icons.d.ts +0 -4
- package/lib/typescript/assets/icons.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
- package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +0 -3
- package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
- package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
- package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts +2 -4
- package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts.map +1 -1
- package/lib/typescript/components/Modals/NewChatModal/UpdNewChatModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/EditUserModal.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/updateMessagesTillLast.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -1
- package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +1 -1
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/networking/outboundQueue.d.ts +16 -0
- package/lib/typescript/networking/outboundQueue.d.ts.map +1 -1
- package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +33 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +18 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/types/models/room.model.d.ts +15 -0
- package/lib/typescript/types/models/room.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +15 -12
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/assets/icons.tsx +0 -19
- package/src/components/MainComponents/ChatRoom.tsx +13 -9
- package/src/components/MainComponents/MessageList.tsx +23 -6
- package/src/components/MainComponents/ProfileImagePlaceholder.tsx +9 -16
- package/src/components/Menu/HeaderRoomListMenu.tsx +11 -105
- package/src/components/Modals/AttachSheet/AttachSheet.tsx +14 -16
- package/src/components/Modals/NewChatModal/ModalContent.tsx +3 -6
- package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +1 -12
- package/src/components/Modals/UserProfileModal/EditUserModal.tsx +25 -9
- package/src/components/styled/SendInput.tsx +10 -0
- package/src/context/xmppProvider.tsx +41 -8
- package/src/helpers/updateMessagesTillLast.tsx +42 -17
- package/src/hooks/useChatRoomFocus.ts +11 -3
- package/src/hooks/useLogout.tsx +7 -0
- package/src/hooks/useSendMessage.tsx +60 -24
- package/src/main.ts +1 -1
- package/src/networking/outboundQueue.ts +29 -0
- package/src/networking/stanzaHandlers.ts +9 -1
- package/src/networking/xmppClient.ts +118 -7
- package/src/roomStore/roomsSlice.ts +20 -2
- package/src/types/models/room.model.ts +15 -0
- package/src/types/types.ts +15 -14
- package/lib/commonjs/helpers/pickImageAsset.js +0 -68
- package/lib/commonjs/helpers/pickImageAsset.js.map +0 -1
- package/lib/module/helpers/pickImageAsset.js +0 -63
- package/lib/module/helpers/pickImageAsset.js.map +0 -1
- package/lib/typescript/helpers/pickImageAsset.d.ts +0 -27
- package/lib/typescript/helpers/pickImageAsset.d.ts.map +0 -1
- 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
|
|
package/src/types/types.ts
CHANGED
|
@@ -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
|
-
};
|