@antzsoft/chat-core 1.0.7 → 1.0.9
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/README.md +182 -0
- package/dist/index.cjs +119 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -2
- package/dist/index.d.ts +49 -2
- package/dist/index.js +118 -7
- package/dist/index.js.map +1 -1
- package/docs/integration-guide.html +456 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1122,6 +1122,166 @@ result.failed.forEach((f) => console.error('Failed:', f.filename, f.error));
|
|
|
1122
1122
|
|
|
1123
1123
|
---
|
|
1124
1124
|
|
|
1125
|
+
## File Compression
|
|
1126
|
+
|
|
1127
|
+
Compression is optional and fully backward compatible. It runs entirely client-side before the upload starts — the server receives the already-compressed file with the correct size and MIME type.
|
|
1128
|
+
|
|
1129
|
+
### How it works
|
|
1130
|
+
|
|
1131
|
+
When `platformCompressFn` is provided and `compression.enabled` is `true` (the default when a compressor is supplied), `uploadBatch` compresses each file before requesting a presigned URL:
|
|
1132
|
+
|
|
1133
|
+
1. Determine strategy per file (`image` → WebP/JPEG resize+encode, `gzip` → text/doc compression, `skip` → no-op)
|
|
1134
|
+
2. Run `platformCompressFn(file, compressionConfig)` — returns a `CompressedFile`
|
|
1135
|
+
3. If compressed result is **larger** than the original, the original is used instead (automatic fallback)
|
|
1136
|
+
4. Request presigned URL with the compressed size and MIME type
|
|
1137
|
+
5. Upload the compressed bytes
|
|
1138
|
+
6. Store `metadata.compressed`, `metadata.originalSize`, `metadata.compressionAlgorithm` on the file record
|
|
1139
|
+
|
|
1140
|
+
### Strategy by file type
|
|
1141
|
+
|
|
1142
|
+
| File type | Strategy | Algorithm | Notes |
|
|
1143
|
+
|-----------|----------|-----------|-------|
|
|
1144
|
+
| `image/jpeg`, `image/png`, `image/gif`, `image/bmp`, `image/tiff` | `image` | `webp` (web) / `jpeg` (RN) | Resize to `imageMaxDimension` first |
|
|
1145
|
+
| `image/webp` | `image` | `webp` | Re-encode at target quality |
|
|
1146
|
+
| `image/svg+xml` | `gzip` | `gzip` | SVG is XML text |
|
|
1147
|
+
| `text/plain`, `text/csv`, `text/markdown`, `application/json`, `text/xml`, `application/xml`, `text/yaml`, `application/rtf` | `gzip` | `gzip` | Only when `compressDocuments: true` |
|
|
1148
|
+
| `video/*`, `audio/*`, `application/pdf`, `application/zip`, Office formats (`.docx`, `.xlsx`, `.pptx`) | `skip` | `none` | Already compressed |
|
|
1149
|
+
|
|
1150
|
+
### Configuration
|
|
1151
|
+
|
|
1152
|
+
Pass `compression` and `platformCompressFn` in the config:
|
|
1153
|
+
|
|
1154
|
+
```typescript
|
|
1155
|
+
import { AntzChatClient } from '@antzsoft/chat-core';
|
|
1156
|
+
|
|
1157
|
+
const client = new AntzChatClient({
|
|
1158
|
+
apiUrl: 'https://api.yourapp.com/api/v1',
|
|
1159
|
+
authToken: 'your-token',
|
|
1160
|
+
platformUploadFn: myUploadFn,
|
|
1161
|
+
persistStorage: myStorage,
|
|
1162
|
+
|
|
1163
|
+
// Optional — omit to disable compression entirely
|
|
1164
|
+
platformCompressFn: myCompressFn,
|
|
1165
|
+
compression: {
|
|
1166
|
+
enabled: true, // default: true when platformCompressFn is provided
|
|
1167
|
+
imageQuality: 0.85, // 0–1, default: 0.85
|
|
1168
|
+
imageMaxDimension: 1920, // longest side cap in px, default: 1920
|
|
1169
|
+
compressDocuments: true, // gzip text/json/csv/xml/yaml, default: true
|
|
1170
|
+
},
|
|
1171
|
+
});
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
### Opt out completely
|
|
1175
|
+
|
|
1176
|
+
```typescript
|
|
1177
|
+
// Disable compression — files upload as-is
|
|
1178
|
+
const client = new AntzChatClient({
|
|
1179
|
+
...
|
|
1180
|
+
compression: { enabled: false },
|
|
1181
|
+
});
|
|
1182
|
+
```
|
|
1183
|
+
|
|
1184
|
+
### Implementing `platformCompressFn` for Node.js
|
|
1185
|
+
|
|
1186
|
+
The web and RN SDKs provide their own compressors automatically. For Node.js / `AntzChatClient` direct usage, implement it with `sharp` and `zlib`:
|
|
1187
|
+
|
|
1188
|
+
```typescript
|
|
1189
|
+
import sharp from 'sharp';
|
|
1190
|
+
import zlib from 'zlib';
|
|
1191
|
+
import { promisify } from 'util';
|
|
1192
|
+
import type { PlatformCompressFn } from '@antzsoft/chat-core';
|
|
1193
|
+
import { getCompressionStrategy } from '@antzsoft/chat-core';
|
|
1194
|
+
import * as fs from 'fs/promises';
|
|
1195
|
+
import * as path from 'path';
|
|
1196
|
+
import * as os from 'os';
|
|
1197
|
+
|
|
1198
|
+
const gzip = promisify(zlib.gzip);
|
|
1199
|
+
|
|
1200
|
+
export const nodeCompressFn: PlatformCompressFn = async (file, options) => {
|
|
1201
|
+
const strategy = getCompressionStrategy(file.type, options);
|
|
1202
|
+
const noop = { ...file, originalSize: file.size, compressed: false, compressionAlgorithm: 'none' as const };
|
|
1203
|
+
|
|
1204
|
+
if (strategy === 'image') {
|
|
1205
|
+
try {
|
|
1206
|
+
const buffer = await sharp(file.uri)
|
|
1207
|
+
.resize({ width: options.imageMaxDimension, height: options.imageMaxDimension, fit: 'inside', withoutEnlargement: true })
|
|
1208
|
+
.jpeg({ quality: Math.round(options.imageQuality * 100) })
|
|
1209
|
+
.toBuffer();
|
|
1210
|
+
|
|
1211
|
+
if (buffer.length >= file.size) return noop;
|
|
1212
|
+
|
|
1213
|
+
const tmpPath = path.join(os.tmpdir(), `${Date.now()}.jpg`);
|
|
1214
|
+
await fs.writeFile(tmpPath, buffer);
|
|
1215
|
+
|
|
1216
|
+
return {
|
|
1217
|
+
uri: tmpPath,
|
|
1218
|
+
name: file.name.replace(/\.[^.]+$/, '.jpg'),
|
|
1219
|
+
type: 'image/jpeg',
|
|
1220
|
+
size: buffer.length,
|
|
1221
|
+
originalSize: file.size,
|
|
1222
|
+
compressed: true,
|
|
1223
|
+
compressionAlgorithm: 'jpeg' as const,
|
|
1224
|
+
};
|
|
1225
|
+
} catch {
|
|
1226
|
+
return noop;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
if (strategy === 'gzip') {
|
|
1231
|
+
try {
|
|
1232
|
+
const input = await fs.readFile(file.uri);
|
|
1233
|
+
const compressed = await gzip(input);
|
|
1234
|
+
|
|
1235
|
+
if (compressed.length >= file.size) return noop;
|
|
1236
|
+
|
|
1237
|
+
const tmpPath = path.join(os.tmpdir(), `${Date.now()}.gz`);
|
|
1238
|
+
await fs.writeFile(tmpPath, compressed);
|
|
1239
|
+
|
|
1240
|
+
return {
|
|
1241
|
+
uri: tmpPath,
|
|
1242
|
+
name: file.name + '.gz',
|
|
1243
|
+
type: file.type,
|
|
1244
|
+
size: compressed.length,
|
|
1245
|
+
originalSize: file.size,
|
|
1246
|
+
compressed: true,
|
|
1247
|
+
compressionAlgorithm: 'gzip' as const,
|
|
1248
|
+
};
|
|
1249
|
+
} catch {
|
|
1250
|
+
return noop;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
return noop;
|
|
1255
|
+
};
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
Then pass it to the client:
|
|
1259
|
+
|
|
1260
|
+
```typescript
|
|
1261
|
+
const client = new AntzChatClient({
|
|
1262
|
+
apiUrl: 'https://api.yourapp.com/api/v1',
|
|
1263
|
+
authToken: process.env.AUTH_TOKEN,
|
|
1264
|
+
platformUploadFn: myUploadFn,
|
|
1265
|
+
persistStorage: myStorage,
|
|
1266
|
+
platformCompressFn: nodeCompressFn,
|
|
1267
|
+
compression: { imageQuality: 0.85, imageMaxDimension: 1920 },
|
|
1268
|
+
});
|
|
1269
|
+
```
|
|
1270
|
+
|
|
1271
|
+
### `CompressedFile` type
|
|
1272
|
+
|
|
1273
|
+
```typescript
|
|
1274
|
+
interface CompressedFile extends UploadableFile {
|
|
1275
|
+
originalSize: number;
|
|
1276
|
+
compressed: boolean;
|
|
1277
|
+
compressionAlgorithm: 'webp' | 'jpeg' | 'gzip' | 'none';
|
|
1278
|
+
}
|
|
1279
|
+
```
|
|
1280
|
+
|
|
1281
|
+
The `CompressedFile` extends `UploadableFile` — it is a drop-in replacement everywhere `UploadableFile` is accepted.
|
|
1282
|
+
|
|
1283
|
+
---
|
|
1284
|
+
|
|
1125
1285
|
### Devices API (`devicesApi`)
|
|
1126
1286
|
|
|
1127
1287
|
Used for push notification token registration. The SDK does not call this automatically — the host app is responsible for obtaining the device token from the OS and registering it.
|
|
@@ -1926,6 +2086,12 @@ interface Conversation {
|
|
|
1926
2086
|
interface ConversationSettings {
|
|
1927
2087
|
onlyAdminsCanMessage?: boolean;
|
|
1928
2088
|
onlyAdminsCanAddMembers?: boolean;
|
|
2089
|
+
messageConfig?: MessageConfig;
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
interface MessageConfig {
|
|
2093
|
+
editWindowSeconds?: number;
|
|
2094
|
+
deleteWindowSeconds?: number;
|
|
1929
2095
|
}
|
|
1930
2096
|
```
|
|
1931
2097
|
|
|
@@ -1993,6 +2159,7 @@ interface SendMessageAttachment {
|
|
|
1993
2159
|
filename: string;
|
|
1994
2160
|
mimeType: string;
|
|
1995
2161
|
size: number;
|
|
2162
|
+
duration?: number; // seconds — required for audio/video so receivers can render a player UI
|
|
1996
2163
|
}
|
|
1997
2164
|
```
|
|
1998
2165
|
|
|
@@ -2189,6 +2356,21 @@ document.querySelectorAll('[data-conv-id]').forEach((el) => {
|
|
|
2189
2356
|
|
|
2190
2357
|
## Changelog
|
|
2191
2358
|
|
|
2359
|
+
### v1.0.9
|
|
2360
|
+
- **Socket reconnect resilience for `sendMessage`** — On Android, the OS suspends idle WebSocket connections during long audio recordings. `sendMessage` now waits up to 15 seconds for Socket.IO to auto-reconnect before sending, instead of immediately failing with "Socket not connected". Audio messages go through without error after upload. **No API change.**
|
|
2361
|
+
- **`settings` and `participantCount` now returned in conversation responses** — All conversation API responses and socket events (`conversation_created`, `conversation_updated`, etc.) now include `settings` (`onlyAdminsCanMessage`, `onlyAdminsCanAddMembers`, `messageConfig.editWindowSeconds`, `messageConfig.deleteWindowSeconds`) and `participantCount`. Previously these were server-side only. **No SDK change required — fields were already in the `Conversation` type as optional.**
|
|
2362
|
+
- **Fix: 500 error when leaving a group** — Leaving a group conversation returned an internal server error (leave still succeeded) for groups with no `messageId` in their stored `lastMessage`. The response builder now safely skips `lastMessage` when its `messageId` is missing. **No SDK change required.**
|
|
2363
|
+
- **Fix: empty `text: ""` stored on attachment-only messages** — Sending a message with an attachment and `text: ""` was persisting an empty string instead of `undefined`, causing the conversation-list preview to show blank instead of the filename or "Attachment". Both the HTTP and socket paths now trim and treat empty strings as absent before saving. **No SDK change required.**
|
|
2364
|
+
- **Fix: `participant_left` not received by users outside the open conversation** — The `participant_left` socket event was only broadcast to the `conversation:<id>` room, which users only join when they open that specific conversation. Users on the conversation-list screen never received it and saw stale participant counts. The server now also emits directly to each remaining participant's personal `user:<tenantId>:<userId>` room (joined on connect), skipping users already in the conversation room to avoid double-delivery. **No SDK change required.**
|
|
2365
|
+
|
|
2366
|
+
### v1.0.8
|
|
2367
|
+
- **`duration` field in `SendMessageAttachment`** — Pass `duration` (seconds) when sending audio or video. Server now stores and returns it in `new_message` and message list responses. **Action required (RN):** Omitting it on React Native can crash native audio player libraries on the receiver side; always pass it for audio/video. Web is unaffected.
|
|
2368
|
+
- **File compression** — `uploadBatch` now accepts optional `platformCompressFn` + `compressionConfig` args. Fully backward compatible — existing callers unchanged. Web/RN SDKs wire this in automatically; Node.js users can supply `nodeCompressFn` manually. No action required unless opting in on Node.
|
|
2369
|
+
- **Removed members keep read-only access** — Server behavior change. Removed participants stay in their conversation list and can read history but cannot write. Socket room membership ends immediately on removal. **No SDK change required.**
|
|
2370
|
+
- **Admin delete is hide-only** — Server behavior change. Deleting a conversation sets `isHidden` for the requester only; other participants are unaffected. **No SDK change required.**
|
|
2371
|
+
- **Fix: `lastMessage.status` stuck as `deleted`** — Server now explicitly resets `status: 'active'` on both REST and WebSocket paths when a new message is sent. **No client action required.**
|
|
2372
|
+
- **Fix: `duration` stored from sender payload** — `SendMessageAttachment.duration` is now persisted and echoed back. The `SendMessageAttachment` interface in this package is unchanged (field was already present as optional).
|
|
2373
|
+
|
|
2192
2374
|
### v1.0.7
|
|
2193
2375
|
- **`deliveredTo` per-user delivery timestamps** — All message responses now include `deliveredTo: Array<{ userId, deliveredAt }>` alongside `readBy`. The `Message` type updated: `readBy` changed from `string[]` to `Array<{ userId, readAt }>`. The `message_delivered` socket event payload changed from `{ deliveredTo: string[], deliveredAt }` to `{ deliveredTo: Array<{ userId, deliveredAt }> }`.
|
|
2194
2376
|
- **Audio support for `.m4a` / `audio/x-m4a`** — `audio/m4a` and `audio/x-m4a` MIME types are now accepted for audio attachments.
|
package/dist/index.cjs
CHANGED
|
@@ -102,6 +102,7 @@ __export(src_exports, {
|
|
|
102
102
|
disconnectSocket: () => disconnectSocket,
|
|
103
103
|
getApiClient: () => getApiClient,
|
|
104
104
|
getAuthStore: () => getAuthStore,
|
|
105
|
+
getCompressionStrategy: () => getCompressionStrategy,
|
|
105
106
|
getSocket: () => getSocket,
|
|
106
107
|
getSocketStatus: () => getSocketStatus,
|
|
107
108
|
initApiClient: () => initApiClient,
|
|
@@ -168,6 +169,13 @@ function resolveConfig(config) {
|
|
|
168
169
|
onProgress: config.upload?.onProgress
|
|
169
170
|
},
|
|
170
171
|
platformUploadFn: config.platformUploadFn,
|
|
172
|
+
platformCompressFn: config.platformCompressFn,
|
|
173
|
+
compression: {
|
|
174
|
+
enabled: config.compression?.enabled ?? config.platformCompressFn != null,
|
|
175
|
+
imageQuality: config.compression?.imageQuality ?? 0.85,
|
|
176
|
+
imageMaxDimension: config.compression?.imageMaxDimension ?? 1920,
|
|
177
|
+
compressDocuments: config.compression?.compressDocuments ?? true
|
|
178
|
+
},
|
|
171
179
|
persistStorage: config.persistStorage,
|
|
172
180
|
messagePageSize: config.messagePageSize ?? 40,
|
|
173
181
|
starredMessagePageSize: config.starredMessagePageSize ?? 30,
|
|
@@ -175,6 +183,68 @@ function resolveConfig(config) {
|
|
|
175
183
|
};
|
|
176
184
|
}
|
|
177
185
|
|
|
186
|
+
// src/compression/compress.ts
|
|
187
|
+
var GZIP_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
188
|
+
"text/plain",
|
|
189
|
+
"text/csv",
|
|
190
|
+
"text/markdown",
|
|
191
|
+
"text/x-markdown",
|
|
192
|
+
"text/xml",
|
|
193
|
+
"application/xml",
|
|
194
|
+
"text/yaml",
|
|
195
|
+
"text/x-yaml",
|
|
196
|
+
"application/x-yaml",
|
|
197
|
+
"application/rtf",
|
|
198
|
+
"text/rtf",
|
|
199
|
+
"application/json",
|
|
200
|
+
"image/svg+xml"
|
|
201
|
+
]);
|
|
202
|
+
var IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
203
|
+
"image/jpeg",
|
|
204
|
+
"image/png",
|
|
205
|
+
"image/gif",
|
|
206
|
+
"image/webp",
|
|
207
|
+
"image/bmp",
|
|
208
|
+
"image/tiff"
|
|
209
|
+
]);
|
|
210
|
+
var SKIP_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
211
|
+
"video/mp4",
|
|
212
|
+
"video/webm",
|
|
213
|
+
"video/quicktime",
|
|
214
|
+
"audio/mpeg",
|
|
215
|
+
"audio/wav",
|
|
216
|
+
"audio/ogg",
|
|
217
|
+
"audio/webm",
|
|
218
|
+
"audio/mp4",
|
|
219
|
+
"application/zip",
|
|
220
|
+
"application/pdf",
|
|
221
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
222
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
223
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
224
|
+
]);
|
|
225
|
+
function getCompressionStrategy(mimeType, config) {
|
|
226
|
+
if (SKIP_MIME_TYPES.has(mimeType)) return "skip";
|
|
227
|
+
if (IMAGE_MIME_TYPES.has(mimeType)) return "image";
|
|
228
|
+
if (config.compressDocuments && GZIP_MIME_TYPES.has(mimeType)) return "gzip";
|
|
229
|
+
return "skip";
|
|
230
|
+
}
|
|
231
|
+
async function compressFile(file, platformCompressFn, config) {
|
|
232
|
+
const noop = {
|
|
233
|
+
...file,
|
|
234
|
+
originalSize: file.size,
|
|
235
|
+
compressed: false,
|
|
236
|
+
compressionAlgorithm: "none"
|
|
237
|
+
};
|
|
238
|
+
if (!config.enabled || !platformCompressFn) return noop;
|
|
239
|
+
const strategy = getCompressionStrategy(file.type, config);
|
|
240
|
+
if (strategy === "skip") return noop;
|
|
241
|
+
try {
|
|
242
|
+
return await platformCompressFn(file, config);
|
|
243
|
+
} catch {
|
|
244
|
+
return noop;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
178
248
|
// src/api/client.ts
|
|
179
249
|
var import_axios = __toESM(require("axios"), 1);
|
|
180
250
|
var _tokenStore = null;
|
|
@@ -571,12 +641,22 @@ var storageApi = {
|
|
|
571
641
|
return data;
|
|
572
642
|
}
|
|
573
643
|
};
|
|
574
|
-
async function uploadBatch(files, platformUploadFn, conversationId, onProgress) {
|
|
575
|
-
const
|
|
644
|
+
async function uploadBatch(files, platformUploadFn, conversationId, onProgress, platformCompressFn, compressionConfig) {
|
|
645
|
+
const compressedFiles = await Promise.all(
|
|
646
|
+
files.map((f) => compressFile(f, platformCompressFn, compressionConfig ?? { enabled: false, imageQuality: 0.85, imageMaxDimension: 1920, compressDocuments: true }))
|
|
647
|
+
);
|
|
648
|
+
const requests = compressedFiles.map((f) => ({
|
|
576
649
|
filename: f.name,
|
|
577
650
|
mimeType: f.type,
|
|
578
651
|
size: f.size,
|
|
579
|
-
conversationId
|
|
652
|
+
conversationId,
|
|
653
|
+
...f.compressed && {
|
|
654
|
+
metadata: {
|
|
655
|
+
compressed: true,
|
|
656
|
+
originalSize: f.originalSize,
|
|
657
|
+
compressionAlgorithm: f.compressionAlgorithm
|
|
658
|
+
}
|
|
659
|
+
}
|
|
580
660
|
}));
|
|
581
661
|
const { urls, errors: requestErrors } = await storageApi.requestPresignedUrlBatch(requests);
|
|
582
662
|
const progressMap = {};
|
|
@@ -590,7 +670,7 @@ async function uploadBatch(files, platformUploadFn, conversationId, onProgress)
|
|
|
590
670
|
const failed = [...requestErrors];
|
|
591
671
|
await Promise.all(
|
|
592
672
|
urls.map(async (presigned, idx) => {
|
|
593
|
-
const file =
|
|
673
|
+
const file = compressedFiles[idx];
|
|
594
674
|
progressMap[idx] = 0;
|
|
595
675
|
try {
|
|
596
676
|
await platformUploadFn(presigned, file, (pct) => {
|
|
@@ -785,8 +865,32 @@ function refreshSocketAuth() {
|
|
|
785
865
|
|
|
786
866
|
// src/socket/emitters.ts
|
|
787
867
|
var ACK_TIMEOUT = 5e3;
|
|
788
|
-
|
|
789
|
-
|
|
868
|
+
var RECONNECT_WAIT_TIMEOUT = 15e3;
|
|
869
|
+
function waitForReconnect() {
|
|
870
|
+
return new Promise((resolve, reject) => {
|
|
871
|
+
const timer = setTimeout(() => {
|
|
872
|
+
unsubscribe();
|
|
873
|
+
reject(new Error("[AntzChat] Socket reconnect timeout"));
|
|
874
|
+
}, RECONNECT_WAIT_TIMEOUT);
|
|
875
|
+
const unsubscribe = onSocketStatus((status) => {
|
|
876
|
+
if (status === "connected") {
|
|
877
|
+
clearTimeout(timer);
|
|
878
|
+
unsubscribe();
|
|
879
|
+
resolve();
|
|
880
|
+
} else if (status === "error") {
|
|
881
|
+
clearTimeout(timer);
|
|
882
|
+
unsubscribe();
|
|
883
|
+
reject(new Error("[AntzChat] Socket reconnect failed"));
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
async function withAck(event, payload) {
|
|
889
|
+
let socket = tryGetSocket();
|
|
890
|
+
if (!socket) {
|
|
891
|
+
await waitForReconnect();
|
|
892
|
+
socket = tryGetSocket();
|
|
893
|
+
}
|
|
790
894
|
if (!socket) return Promise.reject(new Error(`[AntzChat] Socket not connected (event: ${event})`));
|
|
791
895
|
return new Promise((resolve, reject) => {
|
|
792
896
|
const timer = setTimeout(() => reject(new Error(`Socket ack timeout: ${event}`)), ACK_TIMEOUT);
|
|
@@ -985,7 +1089,14 @@ var AntzChatClient = class {
|
|
|
985
1089
|
disconnectSocket();
|
|
986
1090
|
}
|
|
987
1091
|
uploadFiles(files, conversationId) {
|
|
988
|
-
return uploadBatch(
|
|
1092
|
+
return uploadBatch(
|
|
1093
|
+
files,
|
|
1094
|
+
this._config.platformUploadFn,
|
|
1095
|
+
conversationId,
|
|
1096
|
+
this._config.upload.onProgress,
|
|
1097
|
+
this._config.platformCompressFn,
|
|
1098
|
+
this._config.compression
|
|
1099
|
+
);
|
|
989
1100
|
}
|
|
990
1101
|
async uploadIcon(conversationId, file) {
|
|
991
1102
|
const result = await this.uploadFiles([file], conversationId);
|
|
@@ -1005,6 +1116,7 @@ var AntzChatClient = class {
|
|
|
1005
1116
|
disconnectSocket,
|
|
1006
1117
|
getApiClient,
|
|
1007
1118
|
getAuthStore,
|
|
1119
|
+
getCompressionStrategy,
|
|
1008
1120
|
getSocket,
|
|
1009
1121
|
getSocketStatus,
|
|
1010
1122
|
initApiClient,
|