@poolse/react-native 2.0.11 → 2.0.13

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/dist/index.cjs CHANGED
@@ -7,6 +7,7 @@ var jsxRuntime = require('react/jsx-runtime');
7
7
  var reactNativeSvg = require('react-native-svg');
8
8
  var ImagePicker = require('expo-image-picker');
9
9
  var DocumentPicker = require('expo-document-picker');
10
+ var expoImageManipulator = require('expo-image-manipulator');
10
11
 
11
12
  function _interopNamespace(e) {
12
13
  if (e && e.__esModule) return e;
@@ -1183,24 +1184,84 @@ async function uriToBlob(uri) {
1183
1184
  }
1184
1185
  return res.blob();
1185
1186
  }
1187
+ var COMPRESSION_LONG_SIDE_PX = 1600;
1188
+ var COMPRESSION_QUALITY = 0.75;
1189
+ function getImageSize(uri) {
1190
+ return new Promise((resolve, reject) => {
1191
+ reactNative.Image.getSize(uri, (width, height) => resolve({ width, height }), reject);
1192
+ });
1193
+ }
1194
+ async function compressImage({
1195
+ uri,
1196
+ width,
1197
+ height,
1198
+ filename
1199
+ }) {
1200
+ let w = width;
1201
+ let h = height;
1202
+ if (!w || !h) {
1203
+ try {
1204
+ const size = await getImageSize(uri);
1205
+ w = size.width;
1206
+ h = size.height;
1207
+ } catch {
1208
+ w = 0;
1209
+ h = 0;
1210
+ }
1211
+ }
1212
+ const longSide = Math.max(w ?? 0, h ?? 0);
1213
+ const scale = longSide > COMPRESSION_LONG_SIDE_PX ? COMPRESSION_LONG_SIDE_PX / longSide : 1;
1214
+ const actions = scale < 1 && w && h ? [{ resize: { width: Math.round(w * scale), height: Math.round(h * scale) } }] : [];
1215
+ const result = await expoImageManipulator.manipulateAsync(uri, actions, {
1216
+ compress: COMPRESSION_QUALITY,
1217
+ format: expoImageManipulator.SaveFormat.WEBP
1218
+ });
1219
+ const blob = await uriToBlob(result.uri);
1220
+ const base = (filename ?? `image-${Date.now()}`).replace(/\.[^.]+$/, "");
1221
+ return {
1222
+ blob,
1223
+ contentType: "image/webp",
1224
+ filename: `${base}.webp`
1225
+ };
1226
+ }
1186
1227
  async function defaultAdapter(kind) {
1187
1228
  if (kind === "image") {
1188
1229
  const res2 = await ImagePicker__namespace.launchImageLibraryAsync({
1189
1230
  mediaTypes: "images",
1190
- quality: 0.85
1231
+ // Quality 1 — picker hands back the source as-is and we do the
1232
+ // compression ourselves below. Letting the picker re-encode
1233
+ // first just chains two lossy passes.
1234
+ quality: 1
1191
1235
  });
1192
1236
  if (res2.canceled) return [];
1193
1237
  return Promise.all(
1194
1238
  res2.assets.map(async (asset) => {
1195
- const blob = await uriToBlob(asset.uri);
1196
- const contentType = asset.mimeType ?? blob.type ?? "image/jpeg";
1197
- return {
1198
- body: blob,
1199
- contentType,
1200
- byteSize: asset.fileSize ?? blob.size,
1201
- filename: asset.fileName ?? `image-${Date.now()}.jpg`,
1202
- _previewUri: asset.uri
1203
- };
1239
+ try {
1240
+ const compressed = await compressImage({
1241
+ uri: asset.uri,
1242
+ width: asset.width,
1243
+ height: asset.height,
1244
+ filename: asset.fileName ?? `image-${Date.now()}`
1245
+ });
1246
+ return {
1247
+ body: compressed.blob,
1248
+ contentType: compressed.contentType,
1249
+ byteSize: compressed.blob.size,
1250
+ filename: compressed.filename,
1251
+ _previewUri: asset.uri
1252
+ };
1253
+ } catch (err) {
1254
+ console.warn("[poolse/picker] image compression failed, sending original:", err);
1255
+ const blob = await uriToBlob(asset.uri);
1256
+ const contentType = asset.mimeType ?? blob.type ?? "image/jpeg";
1257
+ return {
1258
+ body: blob,
1259
+ contentType,
1260
+ byteSize: asset.fileSize ?? blob.size,
1261
+ filename: asset.fileName ?? `image-${Date.now()}.jpg`,
1262
+ _previewUri: asset.uri
1263
+ };
1264
+ }
1204
1265
  })
1205
1266
  );
1206
1267
  }
@@ -1211,6 +1272,24 @@ async function defaultAdapter(kind) {
1211
1272
  if (res.canceled) return [];
1212
1273
  return Promise.all(
1213
1274
  res.assets.map(async (asset) => {
1275
+ const isImage = (asset.mimeType ?? "").startsWith("image/");
1276
+ if (isImage) {
1277
+ try {
1278
+ const compressed = await compressImage({
1279
+ uri: asset.uri,
1280
+ filename: asset.name
1281
+ });
1282
+ return {
1283
+ body: compressed.blob,
1284
+ contentType: compressed.contentType,
1285
+ byteSize: compressed.blob.size,
1286
+ filename: compressed.filename,
1287
+ _previewUri: asset.uri
1288
+ };
1289
+ } catch (err) {
1290
+ console.warn("[poolse/picker] image compression failed, sending original:", err);
1291
+ }
1292
+ }
1214
1293
  const blob = await uriToBlob(asset.uri);
1215
1294
  const contentType = asset.mimeType ?? blob.type ?? "application/octet-stream";
1216
1295
  return {
@@ -1499,14 +1578,17 @@ var MessageComposer = react.forwardRef(
1499
1578
  const submitDisabled = disabled || sending || isUploading || value.trim().length === 0 && readyAttachmentIds.length === 0;
1500
1579
  const handleSend = async () => {
1501
1580
  if (submitDisabled) return;
1581
+ const body = value.trim();
1582
+ const replyId = replyingTo?.id;
1583
+ const attachmentIds = readyAttachmentIds;
1584
+ setValue("");
1585
+ upload.reset();
1502
1586
  setSending(true);
1503
1587
  try {
1504
- await onSend(value.trim(), {
1505
- ...replyingTo ? { quoted_message_id: replyingTo.id } : {},
1506
- ...readyAttachmentIds.length > 0 ? { attachment_ids: readyAttachmentIds } : {}
1588
+ await onSend(body, {
1589
+ ...replyId ? { quoted_message_id: replyId } : {},
1590
+ ...attachmentIds.length > 0 ? { attachment_ids: attachmentIds } : {}
1507
1591
  });
1508
- setValue("");
1509
- upload.reset();
1510
1592
  } finally {
1511
1593
  setSending(false);
1512
1594
  }