@subiz/widget-v4 4.1.216 → 4.1.218

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 (42) hide show
  1. package/assets/less/message.less +83 -0
  2. package/compiled_src/chatbox/AudioAttachments.js +5 -0
  3. package/compiled_src/chatbox/Event.js +9 -2
  4. package/compiled_src/chatbox/FileAttachments.js +9 -3
  5. package/compiled_src/chatbox/ImageAttachments.js +16 -6
  6. package/compiled_src/chatbox/UploadProgress.js +44 -0
  7. package/compiled_src/chatbox/VideoAttachments.js +5 -0
  8. package/compiled_src/store/api.js +77 -78
  9. package/compiled_src/store/api_fake.js +1 -1
  10. package/compiled_src/store/attachments.js +5 -1
  11. package/compiled_src/store/store.js +21 -3
  12. package/dist/{1a12ecfb6db.app.js → 1a12ed33347.app.js} +1 -1
  13. package/dist/{1a12ecfb6db.chat.html → 1a12ed33347.chat.html} +1 -1
  14. package/dist/{1a12ecfb6db.chat.js → 1a12ed33347.chat.js} +1 -1
  15. package/dist/{1a12ecfb6db.form.html → 1a12ed33347.form.html} +1 -1
  16. package/dist/{1a12ecfb6db.form.js → 1a12ed33347.form.js} +1 -1
  17. package/dist/{1a12ecfb6db.index.html → 1a12ed33347.index.html} +1 -1
  18. package/dist/{1a12ecfb6db.library.html → 1a12ed33347.library.html} +1 -1
  19. package/dist/{1a12ecfb6db.library.js → 1a12ed33347.library.js} +1 -1
  20. package/dist/{1a12ecfb6db.preview.html → 1a12ed33347.preview.html} +1 -1
  21. package/dist/{1a12ecfb6db.preview.js → 1a12ed33347.preview.js} +1 -1
  22. package/dist/{1a12ecfb6db.webview.js → 1a12ed33347.webview.js} +1 -1
  23. package/dist/HASH +1 -1
  24. package/package.json +13 -12
  25. package/src/chatbox/AudioAttachments.js +2 -0
  26. package/src/chatbox/Event.js +8 -4
  27. package/src/chatbox/FileAttachments.js +5 -2
  28. package/src/chatbox/ImageAttachments.js +6 -2
  29. package/src/chatbox/UploadProgress.js +21 -0
  30. package/src/chatbox/VideoAttachments.js +2 -0
  31. package/src/store/api.js +66 -81
  32. package/src/store/api_fake.js +1 -1
  33. package/src/store/attachments.js +5 -1
  34. package/src/store/store.js +10 -3
  35. /package/dist/{1a12ecfb6db.127.js → 1a12ed33347.127.js} +0 -0
  36. /package/dist/{1a12ecfb6db.132.js → 1a12ed33347.132.js} +0 -0
  37. /package/dist/{1a12ecfb6db.185.js → 1a12ed33347.185.js} +0 -0
  38. /package/dist/{1a12ecfb6db.27.js → 1a12ed33347.27.js} +0 -0
  39. /package/dist/{1a12ecfb6db.278.js → 1a12ed33347.278.js} +0 -0
  40. /package/dist/{1a12ecfb6db.339.js → 1a12ed33347.339.js} +0 -0
  41. /package/dist/{1a12ecfb6db.459.js → 1a12ed33347.459.js} +0 -0
  42. /package/dist/{1a12ecfb6db.490.js → 1a12ed33347.490.js} +0 -0
@@ -303,6 +303,89 @@ a.message_error {
303
303
  border: 1px solid @gray-200;
304
304
  }
305
305
 
306
+ .image-attachment__preview {
307
+ position: relative;
308
+ display: inline-block;
309
+ vertical-align: top;
310
+ margin-top: 5px;
311
+ border-radius: 7px;
312
+ overflow: hidden;
313
+ max-width: 100%;
314
+
315
+ .image-attachment__img {
316
+ display: block;
317
+ margin: 0;
318
+ }
319
+ }
320
+
321
+ .image-attachment__sending {
322
+ position: absolute;
323
+ inset: 0;
324
+ display: flex;
325
+ align-items: center;
326
+ justify-content: center;
327
+ cursor: wait;
328
+ background: rgba(0, 0, 0, 0.28);
329
+
330
+ &::before {
331
+ content: '';
332
+ position: absolute;
333
+ inset: 0;
334
+ background: @primary-color;
335
+ opacity: 0.3;
336
+ }
337
+ }
338
+
339
+ .image-attachment__progress {
340
+ position: relative;
341
+ width: 96px;
342
+ max-width: 80%;
343
+ color: #fff;
344
+ text-align: center;
345
+ }
346
+
347
+ .image-attachment__progress-label {
348
+ display: block;
349
+ font-size: 13px;
350
+ font-weight: 600;
351
+ margin-bottom: 6px;
352
+ font-variant-numeric: tabular-nums;
353
+ }
354
+
355
+ .image-attachment__progress-track {
356
+ display: block;
357
+ height: 4px;
358
+ border-radius: 4px;
359
+ overflow: hidden;
360
+ background: rgba(255, 255, 255, 0.35);
361
+ }
362
+
363
+ .image-attachment__progress-fill {
364
+ display: block;
365
+ height: 100%;
366
+ border-radius: inherit;
367
+ background: #fff;
368
+ }
369
+
370
+ .file-attachment--sending {
371
+ cursor: wait;
372
+
373
+ .file-attachment--filename { text-decoration: none; }
374
+ }
375
+
376
+ .file-attachment__progress {
377
+ display: block;
378
+ width: 100%;
379
+ min-width: 120px;
380
+ max-width: 100%;
381
+ margin-top: 8px;
382
+ color: @primary-color;
383
+ text-align: right;
384
+
385
+ .image-attachment__progress-track { background: rgba(0, 0, 0, 0.1); }
386
+ .image-attachment__progress-fill { background: @primary-color; }
387
+ }
388
+
306
389
  .audio-attachment {
307
390
  width: 100%;
308
391
  margin: 5px 0 0 0;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = AudioAttachments;
7
+ var _UploadProgress = require("./UploadProgress.js");
7
8
  var _index = _interopRequireDefault(require("../util/index.js"));
8
9
  var _preact = require("preact");
9
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -17,6 +18,10 @@ function AudioAttachments(props) {
17
18
  });
18
19
  if (audios.length === 0) return null;
19
20
  var $audios = _index.default.map(audios, (audio, index) => {
21
+ if (props.sending) return (0, _preact.h)(_UploadProgress.UploadingFile, {
22
+ key: index,
23
+ attachment: audio
24
+ });
20
25
  return (0, _preact.h)("div", {
21
26
  key: index,
22
27
  class: `audio-attachment audio-attachment--${byType}`
@@ -379,6 +379,9 @@ class Event extends _common.Com {
379
379
  class: "sending_dot sending_dot__hide"
380
380
  });
381
381
  }
382
+ const hasFile = _index.default.find(attachments, att => att.type === 'file' || att._file);
383
+ const sendingAttachment = !ev._error && ev.source_event_id === ev.id;
384
+ if (hasFile) $dot = null;
382
385
  let $sender = null;
383
386
  if (this.props.event.mode === 'lead' && _index.default.get(ev, 'by.type') !== 'user') $sender = (0, _preact.h)("div", {
384
387
  class: "pt-3"
@@ -413,16 +416,20 @@ class Event extends _common.Com {
413
416
  }), (0, _preact.h)(_ImageAttachments.default, {
414
417
  store: this.props.store,
415
418
  ev: ev,
419
+ sending: sendingAttachment,
416
420
  ref: this.imageAttachmentRef
417
421
  }), (0, _preact.h)(_AudioAttachments.default, {
418
422
  store: this.props.store,
419
- ev: ev
423
+ ev: ev,
424
+ sending: sendingAttachment
420
425
  }), (0, _preact.h)(_VideoAttachments.default, {
421
426
  store: this.props.store,
422
- ev: ev
427
+ ev: ev,
428
+ sending: sendingAttachment
423
429
  }), (0, _preact.h)(_FileAttachments.default, {
424
430
  store: this.props.store,
425
431
  ev: ev,
432
+ sending: sendingAttachment,
426
433
  ref: this.fileAttachmentRef
427
434
  }), (0, _preact.h)(_ButtonAttachments.default, {
428
435
  store: this.props.store,
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _UploadProgress = _interopRequireDefault(require("./UploadProgress.js"));
7
8
  var _index = _interopRequireDefault(require("../util/index.js"));
8
9
  var _common = require("../common.js");
9
10
  var _preact = require("preact");
@@ -33,19 +34,24 @@ class FileAttachments extends _common.Com {
33
34
  if (files.length === 0) return null;
34
35
  let $files = _index.default.map(files, (file, index) => {
35
36
  let cls = `file-attachment file-attachment--${byType}`;
37
+ if (this.props.sending) cls += ' file-attachment--sending';
36
38
  if (file._true_idx === this.state.focusedIdx) cls += ` just-focused`;
37
39
  return (0, _preact.h)("div", {
38
40
  key: index,
39
- class: cls
41
+ class: cls,
42
+ "aria-busy": !!this.props.sending
40
43
  }, (0, _preact.h)("a", {
41
44
  class: "file-attachment--link",
42
- href: this.props.store.replaceFileUrl(file.url),
45
+ href: this.props.sending ? undefined : this.props.store.replaceFileUrl(file.url),
43
46
  target: "_blank"
44
47
  }, (0, _preact.h)("span", {
45
48
  class: "file-attachment--download mr-2"
46
49
  }), (0, _preact.h)("span", {
47
50
  class: "file-attachment--filename"
48
- }, file.name)));
51
+ }, file.name)), this.props.sending && (0, _preact.h)(_UploadProgress.default, {
52
+ attachment: file,
53
+ compact: true
54
+ }));
49
55
  });
50
56
  return (0, _preact.h)("div", {
51
57
  class: `message-${byType}`
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _UploadProgress = _interopRequireDefault(require("./UploadProgress.js"));
7
8
  var _index = _interopRequireDefault(require("../util/index.js"));
8
9
  var _common = require("../common.js");
9
10
  var _preact = require("preact");
@@ -95,18 +96,25 @@ class ImageAttachment extends _common.Com {
95
96
  if (byType !== 'user') byType = 'agent';
96
97
  let cls = `image-attachment image-attachment--${byType}`;
97
98
  if (image._true_idx === this.state.focusedIdx) cls += ' just-focused';
99
+ const $sending = this.props.sending ? (0, _preact.h)("span", {
100
+ class: "image-attachment__sending"
101
+ }, (0, _preact.h)(_UploadProgress.default, {
102
+ attachment: image
103
+ })) : null;
98
104
  if (!image.width || !image.height) {
99
105
  return (0, _preact.h)("div", {
100
106
  class: cls
101
107
  }, (0, _preact.h)("a", {
102
- href: this.props.store.replaceFileUrl(image.url),
103
- target: "_blank"
108
+ class: "image-attachment__preview",
109
+ href: this.props.sending ? undefined : this.props.store.replaceFileUrl(image.url),
110
+ target: "_blank",
111
+ "aria-busy": !!this.props.sending
104
112
  }, (0, _preact.h)("img", {
105
113
  alt: true,
106
114
  class: "image-attachment__img",
107
115
  src: this.props.store.replaceFileUrl(image.thumbnail_url || image.url),
108
116
  onload: e => this.props.onLoad && this.props.onLoad()
109
- })));
117
+ }), $sending));
110
118
  }
111
119
  let {
112
120
  width,
@@ -121,8 +129,10 @@ class ImageAttachment extends _common.Com {
121
129
  return (0, _preact.h)("div", {
122
130
  class: cls
123
131
  }, (0, _preact.h)("a", {
124
- href: trueUrl,
125
- target: "_blank"
132
+ class: "image-attachment__preview",
133
+ href: this.props.sending ? undefined : trueUrl,
134
+ target: "_blank",
135
+ "aria-busy": !!this.props.sending
126
136
  }, (0, _preact.h)("img", {
127
137
  alt: true,
128
138
  ref: el => {
@@ -135,7 +145,7 @@ class ImageAttachment extends _common.Com {
135
145
  src: url,
136
146
  onload: e => this.props.onLoad && this.props.onLoad(),
137
147
  onerror: e => this.onErrorImage(index)
138
- })));
148
+ }), $sending));
139
149
  }
140
150
  render() {
141
151
  var attachments = _index.default.get(this.props.ev, 'data.message.attachments', []);
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.UploadingFile = UploadingFile;
7
+ exports.default = UploadProgress;
8
+ var _preact = require("preact");
9
+ function UploadProgress({
10
+ attachment,
11
+ compact = false
12
+ }) {
13
+ const progress = attachment._upload?.putDone || attachment._upload?.file ? 100 : attachment._upload?.progress ?? 0;
14
+ return (0, _preact.h)("span", {
15
+ class: 'image-attachment__progress' + (compact ? ' file-attachment__progress' : '')
16
+ }, (0, _preact.h)("span", {
17
+ class: "image-attachment__progress-label"
18
+ }, progress, "%"), (0, _preact.h)("span", {
19
+ class: "image-attachment__progress-track",
20
+ role: "progressbar",
21
+ "aria-label": attachment.name || 'Uploading file',
22
+ "aria-valuemin": 0,
23
+ "aria-valuemax": 100,
24
+ "aria-valuenow": progress
25
+ }, (0, _preact.h)("span", {
26
+ class: "image-attachment__progress-fill",
27
+ ref: el => {
28
+ if (el) el.style.setProperty('width', `${progress}%`, 'important');
29
+ }
30
+ })));
31
+ }
32
+ function UploadingFile({
33
+ attachment
34
+ }) {
35
+ return (0, _preact.h)("div", {
36
+ class: "file-attachment file-attachment--user file-attachment--sending",
37
+ "aria-busy": "true"
38
+ }, (0, _preact.h)("span", {
39
+ class: "file-attachment--filename"
40
+ }, attachment.name), (0, _preact.h)(UploadProgress, {
41
+ attachment: attachment,
42
+ compact: true
43
+ }));
44
+ }
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _UploadProgress = require("./UploadProgress.js");
7
8
  var _index = _interopRequireDefault(require("../util/index.js"));
8
9
  var _common = require("../common.js");
9
10
  var _preact = require("preact");
@@ -22,6 +23,10 @@ class VideoAttachments extends _common.Com {
22
23
  });
23
24
  if (videos.length === 0) return null;
24
25
  var $videos = _index.default.map(videos, (video, index) => {
26
+ if (this.props.sending) return (0, _preact.h)(_UploadProgress.UploadingFile, {
27
+ key: index,
28
+ attachment: video
29
+ });
25
30
  return (0, _preact.h)("div", {
26
31
  key: index,
27
32
  class: `video-attachment video-attachment--${byType}`
@@ -84,89 +84,88 @@ class _default {
84
84
  }));
85
85
  _defineProperty(this, "sendTyping", cid => this.apireq.post(`/accounts/${this.accid}/conversations/${cid}/typing`));
86
86
  _defineProperty(this, "sendLostFocus", () => this.apireq.post(`/accounts/${this.accid}/focuses/${this.uid}/delete`));
87
- _defineProperty(this, "uploadToS3", async file => {
88
- let name = file.name.replace(/\s+/g, '_');
89
- var {
90
- body,
91
- error
92
- } = await this.apireq.setBaseUrl('https://api5.subiz.com.vn/4.1').setQuery({
93
- 'account-id': this.accid,
94
- description: 'upload\n user-client: web-widget',
95
- name: name,
96
- presign: true,
97
- size: file.size,
98
- 'content-type': file.type
99
- }).post('/files');
100
- if (error) return {
101
- body,
102
- error
103
- };
104
- let signedurl = body.signed_url;
105
- let fileid = body.id;
106
- let err = await new Promise(resolve => {
107
- const xhr = new _index.default.XMLHttpRequest();
108
- xhr.open('PUT', signedurl, true);
109
- xhr.setRequestHeader('Content-Type', file.type || '');
110
- xhr.onload = function () {
111
- if (xhr.status === 200) {
112
- resolve();
113
- } else {
114
- resolve(new Error(`Upload failed: ${xhr.statusText}`));
115
- }
116
- };
117
- xhr.onerror = function () {
118
- resolve(new Error('Network error during upload.'));
119
- };
120
- xhr.send(file);
121
- });
122
- if (err) return {
123
- error: err
124
- };
125
- var {
126
- body,
127
- error
128
- } = await this.apireq.setBaseUrl('https://api5.subiz.com.vn/4.1').setQuery({
129
- 'account-id': this.accid
130
- }).post(`/files/${fileid}/uploaded`);
131
- if (error) return {
132
- error
87
+ _defineProperty(this, "attachmentRequest", () => this.apireq.setBaseUrl(new URL('/4.1', this.ApiURL).href).addQuery('x-account-id', this.accid));
88
+ _defineProperty(this, "attachmentJSON", async (path, body, method = 'post') => {
89
+ const result = await this.attachmentRequest()[method](path, body);
90
+ if (result.error || result.body?.error || result.code < 200 || result.code >= 300) {
91
+ throw Object.assign(new Error('Attachment request failed'), {
92
+ code: result.body?.error?.code,
93
+ response: result
94
+ });
95
+ }
96
+ return result.body;
97
+ });
98
+ _defineProperty(this, "uploadAttachment", async (file, state = {}, onProgress = () => {}) => {
99
+ if (file.size > 25000000) return {
100
+ error: 'invalid_field_size',
101
+ body: {
102
+ code: 'invalid_field_size'
103
+ }
133
104
  };
134
- return {
135
- url: _index.default.get(body, 'file.url', '')
105
+ const identity = JSON.stringify([this.accid, this.uid, this.ref, this.mask, this.profile_id, this.tokensession]);
106
+ if (state.identity && state.identity !== identity) throw new Error('Upload identity changed');
107
+ state.identity = identity;
108
+ const checkIdentity = () => {
109
+ if (identity !== JSON.stringify([this.accid, this.uid, this.ref, this.mask, this.profile_id, this.tokensession])) throw new Error('Upload identity changed');
136
110
  };
137
- });
138
- _defineProperty(this, "uploadToS32", async file => {
139
- var {
140
- body,
141
- error
142
- } = await ajax.setBaseUrl('https://api5.subiz.com.vn/4.1').withCredentials(true).setQuery({
143
- 'account-id': this.accid,
144
- description: 'upload\n user-client: web-widget',
145
- name: file.name.replace(/\s+/g, '_'),
111
+ if (state.file) return state.file;
112
+ if (state.upload && !state.putDone && state.upload.upload_expires_at <= _index.default.Date.now()) {
113
+ delete state.upload;
114
+ delete state.key;
115
+ }
116
+ if (!state.key) state.key = _index.default.randomString(36);
117
+ if (!state.metadata) state.metadata = {
118
+ category: 'attachment',
119
+ name: file.name,
120
+ content_type: file.type || 'application/octet-stream',
146
121
  size: file.size,
147
- type: file.type
148
- }).setParser('json').beforeHook((param, done) => {
149
- if (this.token_generator) {
150
- let user_id = this.profile_id;
151
- this.token_generator().then(token => {
152
- if (user_id != this.profile_id) return done(true);
153
- if (!token) return done(false);
154
- if (token == 'error') return done(false);
155
- param.request = param.request.addQuery('x-access-token', token);
156
- return done(true);
157
- });
158
- return;
159
- }
160
- if (this.ref) param.request = param.request.addQuery('x-user-ref', this.ref);else if (this.mask) param.request = param.request.addQuery('x-user-mask', this.mask);
161
- return done(true);
162
- }).post('/files', file);
163
- if (error) return {
164
- body,
165
- error
122
+ ttl_seconds: 0
166
123
  };
167
- return {
168
- url: _index.default.get(body, 'file.url')
124
+ if (!state.upload) {
125
+ const created = await this.attachmentJSON('/uploads', {
126
+ ...state.metadata,
127
+ idempotency_key: state.key
128
+ });
129
+ checkIdentity();
130
+ if (!created.upload?.upload_id || !created.upload.upload_url) throw new Error('Missing upload session');
131
+ state.upload = created.upload;
132
+ }
133
+ if (!state.putDone) {
134
+ checkIdentity();
135
+ const report = percent => {
136
+ if (state.progress === percent) return;
137
+ state.progress = percent;
138
+ onProgress(percent);
139
+ };
140
+ report(0);
141
+ await new Promise((resolve, reject) => {
142
+ const xhr = new _index.default.XMLHttpRequest();
143
+ xhr.upload.onprogress = event => {
144
+ if (event.lengthComputable) report(Math.min(100, Math.floor(event.loaded / event.total * 100)));
145
+ };
146
+ xhr.open('PUT', state.upload.upload_url, true);
147
+ xhr.withCredentials = false;
148
+ Object.entries(state.upload.required_headers || {}).forEach(([key, value]) => xhr.setRequestHeader(key, value));
149
+ xhr.onload = () => xhr.status >= 200 && xhr.status < 300 ? resolve() : reject(new Error(`Upload failed: HTTP ${xhr.status}`));
150
+ xhr.onerror = () => reject(new Error('Network error during upload'));
151
+ xhr.onabort = () => reject(new Error('Upload aborted'));
152
+ xhr.ontimeout = () => reject(new Error('Upload timed out'));
153
+ xhr.send(file);
154
+ });
155
+ report(100);
156
+ state.putDone = true;
157
+ }
158
+ checkIdentity();
159
+ const finished = await this.attachmentJSON(`/uploads/${encodeURIComponent(state.upload.upload_id)}/finish`);
160
+ checkIdentity();
161
+ const f = finished.file;
162
+ if (!f?.id || !f.url || f.error_code) throw new Error('File is not available');
163
+ state.file = {
164
+ url: f.url,
165
+ v: 'cdn',
166
+ file_id: f.id
169
167
  };
168
+ return state.file;
170
169
  });
171
170
  _defineProperty(this, "time", _ => ajax.setBaseUrl(this.ApiURL).withCredentials(true).setParser('json').get('/time'));
172
171
  _defineProperty(this, "updateUser", data => this.apireq.post(`/accounts/${this.accid}/users/${this.uid}`, data));
@@ -55,7 +55,7 @@ class _default {
55
55
  _defineProperty(this, "sendContent", data => OK200);
56
56
  _defineProperty(this, "sendLostFocus", data => OK200);
57
57
  _defineProperty(this, "sendContentView", data => OK200);
58
- _defineProperty(this, "uploadToS3", async file => OK200);
58
+ _defineProperty(this, "uploadAttachment", async file => OK200);
59
59
  _defineProperty(this, "time", _ => Promise.resolve({
60
60
  code: 200,
61
61
  body: new _index.default.Date().toISOString()
@@ -8,7 +8,7 @@ async function uploadAttachments(attachments, upload) {
8
8
  let error, errorMessage;
9
9
  for (const attachment of attachments) {
10
10
  try {
11
- const result = await upload(attachment._file);
11
+ const result = await upload(attachment._file, attachment._upload || (attachment._upload = {}));
12
12
  if (result.body && result.body.code === 'invalid_field_size') {
13
13
  errorMessage = 'cannot_send_too_big_file';
14
14
  }
@@ -17,6 +17,10 @@ async function uploadAttachments(attachments, upload) {
17
17
  continue;
18
18
  }
19
19
  attachment.url = result.url;
20
+ if (result.file_id) {
21
+ attachment.v = 'cdn';
22
+ attachment.file_id = result.file_id;
23
+ }
20
24
  } catch (err) {
21
25
  error = error || err;
22
26
  }
@@ -1368,7 +1368,7 @@ class Store {
1368
1368
  if (att.type !== 'file') return;
1369
1369
  if (!att._file) return;
1370
1370
  files.push(att);
1371
- if (ImageTypes.includes(att._file.type)) {
1371
+ if (!att._upload?.file && ImageTypes.includes(att._file.type)) {
1372
1372
  let {
1373
1373
  width,
1374
1374
  height,
@@ -1382,15 +1382,33 @@ class Store {
1382
1382
  }
1383
1383
  this.onWs(event);
1384
1384
  await this.convoGate.entry();
1385
- const uploaded = await (0, _attachments.uploadAttachments)(files, file => this.api.uploadToS3(file));
1385
+ const uploaded = await (0, _attachments.uploadAttachments)(files, (file, state) => this.api.uploadAttachment(file, state, () => this.pubsub.publish('events', event)));
1386
1386
  event._error = uploaded.error;
1387
1387
  if (uploaded.errorMessage) event._error_message = uploaded.errorMessage;
1388
1388
  if (event._error) return this.onWs(event);
1389
1389
  if (cid && cid.startsWith('cslight')) return;
1390
+ const outgoing = {
1391
+ ...event,
1392
+ data: {
1393
+ ...event.data
1394
+ }
1395
+ };
1396
+ if (event.data.message) outgoing.data.message = {
1397
+ ...event.data.message,
1398
+ attachments: event.data.message.attachments?.map(att => {
1399
+ const {
1400
+ _file,
1401
+ _upload,
1402
+ ...attachment
1403
+ } = att;
1404
+ return attachment;
1405
+ })
1406
+ };
1390
1407
  let {
1391
1408
  body: ret,
1392
1409
  error
1393
- } = await this.api.sendConvoEvent(cid, event);
1410
+ } = await this.api.sendConvoEvent(cid, outgoing);
1411
+ error = error || ret?.error;
1394
1412
  if (error) {
1395
1413
  event._error = error;
1396
1414
  this.onWs(event);