@subiz/widget-v4 4.1.74 → 4.1.75
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/compiled_src/chatbox/Event.js +2 -2
- package/compiled_src/chatbox/Events.js +1 -1
- package/compiled_src/store/api_fake.js +1 -4
- package/compiled_src/store/store.js +3 -3
- package/compiled_src/util/common.js +3 -34
- package/package.json +6 -6
- package/src/chatbox/Event.js +2 -2
- package/src/chatbox/Events.js +2 -1
- package/src/store/api_fake.js +1 -1
- package/src/store/store.js +3 -3
- package/src/util/common.js +2 -29
|
@@ -198,7 +198,7 @@ class Event extends _common.Com {
|
|
|
198
198
|
onSelect: e => this.chooseQuickReply(e)
|
|
199
199
|
}));
|
|
200
200
|
}
|
|
201
|
-
if (_index.default.
|
|
201
|
+
if (_index.default.get(ev, 'data.message.idempotency_key') === ev.id && this.props.store.now() - ev.created < 900) {
|
|
202
202
|
_index.default.setTimeout(() => this.setState({
|
|
203
203
|
refresh: this.state.refresh
|
|
204
204
|
}), 1000);
|
|
@@ -206,7 +206,7 @@ class Event extends _common.Com {
|
|
|
206
206
|
let $dot = (0, _preact.h)("div", {
|
|
207
207
|
class: "sending_dot"
|
|
208
208
|
});
|
|
209
|
-
if (this.props.store.now() - ev.created < 900 || _index.default.
|
|
209
|
+
if (this.props.store.now() - ev.created < 900 || _index.default.get(ev, 'data.message.idempotency_key') !== ev.id) {
|
|
210
210
|
$dot = (0, _preact.h)("div", {
|
|
211
211
|
class: "sending_dot sending_dot__hide"
|
|
212
212
|
});
|
|
@@ -134,7 +134,7 @@ class Events extends _common.Com {
|
|
|
134
134
|
if (_index.default.convoOfEv(newev) !== this.props.cid) return;
|
|
135
135
|
let isBottom = this.isBottom();
|
|
136
136
|
var byme = false;
|
|
137
|
-
if (_index.default.get(newev, 'type') === 'message_sent' && newev.id === _index.default.
|
|
137
|
+
if (_index.default.get(newev, 'type') === 'message_sent' && newev.id === _index.default.get(newev, 'data.message.idempotency_key')) byme = true;
|
|
138
138
|
if (byme || isBottom) this.scrollToBottom();
|
|
139
139
|
}
|
|
140
140
|
async loadConvo() {
|
|
@@ -274,10 +274,7 @@ function makeFakeMessages(accid, convoid, userid, agentid) {
|
|
|
274
274
|
conversation_id: convoid,
|
|
275
275
|
text: 'Xin chào',
|
|
276
276
|
format: 'plaintext',
|
|
277
|
-
|
|
278
|
-
key: 'idempotency',
|
|
279
|
-
value: '"wrueysyjbhqrkiwhsejpqrwqrdkkyaibajdw"'
|
|
280
|
-
}],
|
|
277
|
+
idempotency_key: 'wrueysyjbhqrkiwhsejpqrwqrdkkyaibajdw',
|
|
281
278
|
integration_id: inteid,
|
|
282
279
|
pongs: [{
|
|
283
280
|
member_id: userid,
|
|
@@ -446,7 +446,7 @@ class Store {
|
|
|
446
446
|
var lastmsgsent = events[_index.default.size(events) - 1];
|
|
447
447
|
if (!lastmsgsent) return;
|
|
448
448
|
if (this.g_haveSentSeenM[lastmsgsent.id]) return;
|
|
449
|
-
if (lastmsgsent.id ===
|
|
449
|
+
if (lastmsgsent.id === lastmsgsent.data.message.idempotency_key) return;
|
|
450
450
|
this.api.markAsSeen(id, lastmsgsent.id);
|
|
451
451
|
let convo = this.cache.match('convo_' + id) || {};
|
|
452
452
|
let mem = _index.default.find(convo.members, m => m.id === user.id);
|
|
@@ -683,7 +683,7 @@ class Store {
|
|
|
683
683
|
this.chain.put(cid, oldev.id, _index.default.getMs(oldev.created), oldev);
|
|
684
684
|
}
|
|
685
685
|
if (ev.type === 'message_sent') {
|
|
686
|
-
let idemkey = _index.default.
|
|
686
|
+
let idemkey = _index.default.get(ev, 'data.message.idempotency_key');
|
|
687
687
|
let found = _index.default.find(this.listEvents(cid), oldev => oldev.id === idemkey);
|
|
688
688
|
if (found) {
|
|
689
689
|
this.chain.del(cid, found.id);
|
|
@@ -750,7 +750,7 @@ class Store {
|
|
|
750
750
|
_index.default.convoToEv(cid, event);
|
|
751
751
|
let files = [];
|
|
752
752
|
if (type === 'message_sent') {
|
|
753
|
-
|
|
753
|
+
event.data.message.idempotency_key = idempotency;
|
|
754
754
|
event.data.message.conversation_id = cid;
|
|
755
755
|
await flow.map(event.data.message.attachments, 2, async (att, i) => {
|
|
756
756
|
if (att.type !== 'file') return;
|
|
@@ -20,7 +20,6 @@ exports.formatCurrency = formatCurrency;
|
|
|
20
20
|
exports.getAgentDisplayName = getAgentDisplayName;
|
|
21
21
|
exports.getDayName = getDayName;
|
|
22
22
|
exports.getMs = getMs;
|
|
23
|
-
exports.getMsgField = getMsgField;
|
|
24
23
|
exports.getUrlParameter = getUrlParameter;
|
|
25
24
|
exports.getUserAttr = getUserAttr;
|
|
26
25
|
exports.includes = includes;
|
|
@@ -50,9 +49,7 @@ exports.requestAnimationFrame = void 0;
|
|
|
50
49
|
exports.sameDay = sameDay;
|
|
51
50
|
exports.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded;
|
|
52
51
|
exports.setCss = setCss;
|
|
53
|
-
exports.setInterval = void 0;
|
|
54
|
-
exports.setMsgField = setMsgField;
|
|
55
|
-
exports.setTimeout = void 0;
|
|
52
|
+
exports.setTimeout = exports.setInterval = void 0;
|
|
56
53
|
exports.setUserAttr = setUserAttr;
|
|
57
54
|
exports.shortTime = shortTime;
|
|
58
55
|
exports.size = size;
|
|
@@ -91,16 +88,6 @@ function convoOfEv(ev) {
|
|
|
91
88
|
function convoToEv(convoid, ev) {
|
|
92
89
|
if (!ev) return '';
|
|
93
90
|
switch (ev.type) {
|
|
94
|
-
case 'conversation_state_updated':
|
|
95
|
-
case 'conversation_joined':
|
|
96
|
-
case 'conversation_invited':
|
|
97
|
-
case 'conversation_left':
|
|
98
|
-
case 'conversation_tagged':
|
|
99
|
-
case 'conversation_untagged':
|
|
100
|
-
case 'conversation_typing':
|
|
101
|
-
case 'conversation_rating_requested':
|
|
102
|
-
case 'conversation_rated':
|
|
103
|
-
return op.set(ev, 'data.conversation.id', convoid);
|
|
104
91
|
case 'message_sent':
|
|
105
92
|
case 'message_updated':
|
|
106
93
|
case 'message_pong':
|
|
@@ -108,27 +95,9 @@ function convoToEv(convoid, ev) {
|
|
|
108
95
|
case 'ticket_updated':
|
|
109
96
|
return op.set(ev, 'data.ticket.conversation_id', convoid);
|
|
110
97
|
default:
|
|
111
|
-
return '';
|
|
98
|
+
return op.set(ev, 'data.conversation.id', convoid);
|
|
112
99
|
}
|
|
113
100
|
}
|
|
114
|
-
function setMsgField(ev, key, value) {
|
|
115
|
-
var fields = op.get(ev, 'data.message.fields') || [];
|
|
116
|
-
fields = filter(fields, field => field.key !== key);
|
|
117
|
-
fields.push({
|
|
118
|
-
key: key,
|
|
119
|
-
value: stringify(value)
|
|
120
|
-
});
|
|
121
|
-
op.set(ev, 'data.message.fields', fields);
|
|
122
|
-
}
|
|
123
|
-
function getMsgField(ev, fieldName) {
|
|
124
|
-
var fields = op.get(ev, 'data.message.fields');
|
|
125
|
-
if (size(fields) === 0) return undefined;
|
|
126
|
-
let f = fields.find(f => f.key === fieldName);
|
|
127
|
-
try {
|
|
128
|
-
if (f) return parse(f.value);
|
|
129
|
-
return undefined;
|
|
130
|
-
} catch (e) {}
|
|
131
|
-
}
|
|
132
101
|
function isObject(item) {
|
|
133
102
|
return item && typeof item === 'object' && !Array.isArray(item);
|
|
134
103
|
}
|
|
@@ -975,7 +944,7 @@ function replaceFileUrl(src) {
|
|
|
975
944
|
}
|
|
976
945
|
function unicodeToAscii(str) {
|
|
977
946
|
str = str + '';
|
|
978
|
-
str = str.
|
|
947
|
+
str = str.replaceAll('đ', 'd').replaceAll('Đ', 'D');
|
|
979
948
|
return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
|
980
949
|
}
|
|
981
950
|
function scrollIntoViewIfNeeded($ele) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subiz/widget-v4",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.75",
|
|
4
4
|
"main": "./compiled_src/lib.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "npx webpack serve --config webpack.dev.js",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"@subiz/storage": "0.0.8",
|
|
15
15
|
"@subiz/wsclient": "^4.0.24",
|
|
16
16
|
"cookie_js": "1.4.2",
|
|
17
|
-
"core-js": "^3.
|
|
17
|
+
"core-js": "^3.37.0",
|
|
18
18
|
"css-loader": "5.2.7",
|
|
19
19
|
"file-loader": "^6.2.0",
|
|
20
20
|
"less": "^4.2.0",
|
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
"preact": "10.19.3"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@babel/cli": "^7.24.
|
|
26
|
-
"@babel/core": "^7.24.
|
|
25
|
+
"@babel/cli": "^7.24.5",
|
|
26
|
+
"@babel/core": "^7.24.5",
|
|
27
27
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
28
28
|
"@babel/plugin-transform-react-jsx": "^7.23.4",
|
|
29
|
-
"@babel/preset-env": "^7.24.
|
|
29
|
+
"@babel/preset-env": "^7.24.5",
|
|
30
30
|
"babel-loader": "^9.1.3",
|
|
31
31
|
"babel-plugin-syntax-jsx": "^6.18.0",
|
|
32
32
|
"html-webpack-plugin": "^5.6.0",
|
|
33
|
-
"puppeteer": "^22.
|
|
33
|
+
"puppeteer": "^22.7.1",
|
|
34
34
|
"webpack": "^5.91.0",
|
|
35
35
|
"webpack-bundle-analyzer": "^4.10.2",
|
|
36
36
|
"webpack-cli": "^5.1.4",
|
package/src/chatbox/Event.js
CHANGED
|
@@ -185,14 +185,14 @@ export default class Event extends Com {
|
|
|
185
185
|
)
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
if (sb.
|
|
188
|
+
if (sb.get(ev, 'data.message.idempotency_key') === ev.id && this.props.store.now() - ev.created < 900) {
|
|
189
189
|
sb.setTimeout(() => this.setState({refresh: this.state.refresh}), 1000)
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
// only show sending while the message is send too long (>300ms) but haven't returned from
|
|
193
193
|
// the server
|
|
194
194
|
let $dot = <div class='sending_dot'></div>
|
|
195
|
-
if (this.props.store.now() - ev.created < 900 || sb.
|
|
195
|
+
if (this.props.store.now() - ev.created < 900 || sb.get(ev, 'data.message.idempotency_key') !== ev.id) {
|
|
196
196
|
$dot = <div class='sending_dot sending_dot__hide'></div>
|
|
197
197
|
}
|
|
198
198
|
|
package/src/chatbox/Events.js
CHANGED
|
@@ -146,7 +146,8 @@ export default class Events extends Com {
|
|
|
146
146
|
let isBottom = this.isBottom()
|
|
147
147
|
|
|
148
148
|
var byme = false
|
|
149
|
-
if (sb.get(newev, 'type') === 'message_sent' && newev.id === sb.
|
|
149
|
+
if (sb.get(newev, 'type') === 'message_sent' && newev.id === sb.get(newev, 'data.message.idempotency_key'))
|
|
150
|
+
byme = true
|
|
150
151
|
// scroll to bottom when message is sent by me
|
|
151
152
|
// auto scroll to bottom on new message when we are at the bottom
|
|
152
153
|
if (byme || isBottom) this.scrollToBottom()
|
package/src/store/api_fake.js
CHANGED
|
@@ -247,7 +247,7 @@ function makeFakeMessages(accid, convoid, userid, agentid) {
|
|
|
247
247
|
conversation_id: convoid,
|
|
248
248
|
text: 'Xin chào',
|
|
249
249
|
format: 'plaintext',
|
|
250
|
-
|
|
250
|
+
idempotency_key: 'wrueysyjbhqrkiwhsejpqrwqrdkkyaibajdw',
|
|
251
251
|
integration_id: inteid,
|
|
252
252
|
pongs: [{member_id: userid, type: 'seen', created: 1616213203068}],
|
|
253
253
|
},
|
package/src/store/store.js
CHANGED
|
@@ -505,7 +505,7 @@ export default class Store {
|
|
|
505
505
|
if (this.g_haveSentSeenM[lastmsgsent.id]) return
|
|
506
506
|
|
|
507
507
|
// ignore sending message
|
|
508
|
-
if (lastmsgsent.id ===
|
|
508
|
+
if (lastmsgsent.id === lastmsgsent.data.message.idempotency_key) return
|
|
509
509
|
|
|
510
510
|
// send seen
|
|
511
511
|
this.api.markAsSeen(id, lastmsgsent.id)
|
|
@@ -813,7 +813,7 @@ export default class Store {
|
|
|
813
813
|
}
|
|
814
814
|
|
|
815
815
|
if (ev.type === 'message_sent') {
|
|
816
|
-
let idemkey = sb.
|
|
816
|
+
let idemkey = sb.get(ev, 'data.message.idempotency_key')
|
|
817
817
|
let found = sb.find(this.listEvents(cid), (oldev) => oldev.id === idemkey)
|
|
818
818
|
if (found) {
|
|
819
819
|
// keeping old created so the ui can be static
|
|
@@ -884,7 +884,7 @@ export default class Store {
|
|
|
884
884
|
sb.convoToEv(cid, event)
|
|
885
885
|
let files = []
|
|
886
886
|
if (type === 'message_sent') {
|
|
887
|
-
|
|
887
|
+
event.data.message.idempotency_key = idempotency
|
|
888
888
|
event.data.message.conversation_id = cid
|
|
889
889
|
|
|
890
890
|
// pre upload image files
|
package/src/util/common.js
CHANGED
|
@@ -30,16 +30,6 @@ export function convoOfEv(ev) {
|
|
|
30
30
|
export function convoToEv(convoid, ev) {
|
|
31
31
|
if (!ev) return ''
|
|
32
32
|
switch (ev.type) {
|
|
33
|
-
case 'conversation_state_updated':
|
|
34
|
-
case 'conversation_joined':
|
|
35
|
-
case 'conversation_invited':
|
|
36
|
-
case 'conversation_left':
|
|
37
|
-
case 'conversation_tagged':
|
|
38
|
-
case 'conversation_untagged':
|
|
39
|
-
case 'conversation_typing':
|
|
40
|
-
case 'conversation_rating_requested':
|
|
41
|
-
case 'conversation_rated':
|
|
42
|
-
return op.set(ev, 'data.conversation.id', convoid)
|
|
43
33
|
case 'message_sent':
|
|
44
34
|
case 'message_updated':
|
|
45
35
|
case 'message_pong':
|
|
@@ -47,27 +37,10 @@ export function convoToEv(convoid, ev) {
|
|
|
47
37
|
case 'ticket_updated':
|
|
48
38
|
return op.set(ev, 'data.ticket.conversation_id', convoid)
|
|
49
39
|
default:
|
|
50
|
-
return ''
|
|
40
|
+
return op.set(ev, 'data.conversation.id', convoid)
|
|
51
41
|
}
|
|
52
42
|
}
|
|
53
43
|
|
|
54
|
-
export function setMsgField(ev, key, value) {
|
|
55
|
-
var fields = op.get(ev, 'data.message.fields') || []
|
|
56
|
-
fields = filter(fields, (field) => field.key !== key)
|
|
57
|
-
fields.push({key: key, value: stringify(value)})
|
|
58
|
-
op.set(ev, 'data.message.fields', fields)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function getMsgField(ev, fieldName) {
|
|
62
|
-
var fields = op.get(ev, 'data.message.fields')
|
|
63
|
-
if (size(fields) === 0) return undefined
|
|
64
|
-
let f = fields.find((f) => f.key === fieldName)
|
|
65
|
-
try {
|
|
66
|
-
if (f) return parse(f.value)
|
|
67
|
-
return undefined
|
|
68
|
-
} catch (e) {}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
44
|
function isObject(item) {
|
|
72
45
|
return item && typeof item === 'object' && !Array.isArray(item)
|
|
73
46
|
}
|
|
@@ -1124,7 +1097,7 @@ function replaceFileUrl(src) {
|
|
|
1124
1097
|
export function unicodeToAscii(str) {
|
|
1125
1098
|
str = str + ''
|
|
1126
1099
|
// worka round Đ not work
|
|
1127
|
-
str = str.
|
|
1100
|
+
str = str.replaceAll('đ', 'd').replaceAll('Đ', 'D')
|
|
1128
1101
|
return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
|
|
1129
1102
|
}
|
|
1130
1103
|
|