@subiz/widget-v4 4.1.73 → 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.
Files changed (119) hide show
  1. package/compiled_src/chatbox/Event.js +2 -2
  2. package/compiled_src/chatbox/Events.js +1 -1
  3. package/compiled_src/store/api_fake.js +1 -4
  4. package/compiled_src/store/store.js +22 -15
  5. package/compiled_src/util/common.js +3 -34
  6. package/package.json +7 -7
  7. package/src/chatbox/Event.js +2 -2
  8. package/src/chatbox/Events.js +2 -1
  9. package/src/store/api_fake.js +1 -1
  10. package/src/store/store.js +23 -30
  11. package/src/util/common.js +2 -29
  12. package/dist/127.js +0 -273
  13. package/dist/132.js +0 -2796
  14. package/dist/185.js +0 -1885
  15. package/dist/18eaf7ad0c6.127.js +0 -1
  16. package/dist/18eaf7ad0c6.132.js +0 -1
  17. package/dist/18eaf7ad0c6.185.js +0 -1
  18. package/dist/18eaf7ad0c6.27.js +0 -1
  19. package/dist/18eaf7ad0c6.278.js +0 -1
  20. package/dist/18eaf7ad0c6.459.js +0 -1
  21. package/dist/18eaf7ad0c6.490.js +0 -1
  22. package/dist/18eaf7ad0c6.74.js +0 -1
  23. package/dist/18eaf7ad0c6.997.js +0 -1
  24. package/dist/18eaf7ad0c6.app.js +0 -1
  25. package/dist/18eaf7ad0c6.index.html +0 -33
  26. package/dist/18eaf7ad0c6.library.html +0 -33
  27. package/dist/18eaf7ad0c6.library.js +0 -1
  28. package/dist/18eaf7ad0c6.preview.html +0 -759
  29. package/dist/18eaf7ad0c6.preview.js +0 -1
  30. package/dist/18eaf7ad0c6.screenshoot.js +0 -1
  31. package/dist/18eaf7ad0c6.webview.js +0 -1
  32. package/dist/18ed1c3d33e.127.js +0 -1
  33. package/dist/18ed1c3d33e.132.js +0 -1
  34. package/dist/18ed1c3d33e.185.js +0 -1
  35. package/dist/18ed1c3d33e.27.js +0 -1
  36. package/dist/18ed1c3d33e.278.js +0 -1
  37. package/dist/18ed1c3d33e.459.js +0 -1
  38. package/dist/18ed1c3d33e.490.js +0 -1
  39. package/dist/18ed1c3d33e.74.js +0 -1
  40. package/dist/18ed1c3d33e.997.js +0 -1
  41. package/dist/18ed1c3d33e.app.js +0 -1
  42. package/dist/18ed1c3d33e.index.html +0 -33
  43. package/dist/18ed1c3d33e.library.html +0 -33
  44. package/dist/18ed1c3d33e.library.js +0 -1
  45. package/dist/18ed1c3d33e.preview.html +0 -759
  46. package/dist/18ed1c3d33e.preview.js +0 -1
  47. package/dist/18ed1c3d33e.screenshoot.js +0 -1
  48. package/dist/18ed1c3d33e.webview.js +0 -1
  49. package/dist/27.js +0 -107
  50. package/dist/278.js +0 -406
  51. package/dist/459.js +0 -107
  52. package/dist/490.js +0 -304
  53. package/dist/74.js +0 -372
  54. package/dist/997.js +0 -107
  55. package/dist/HASH +0 -1
  56. package/dist/assets/img/Facebook.64607ec.png +0 -0
  57. package/dist/assets/img/Zalo.6845707.png +0 -0
  58. package/dist/assets/img/award1a.1a58e10.png +0 -0
  59. package/dist/assets/img/award3a.3b74423.png +0 -0
  60. package/dist/assets/img/award4a.ed6ccd4.png +0 -0
  61. package/dist/assets/img/award5.39eb7ae.png +0 -0
  62. package/dist/assets/img/bubble_default.7d5e4ab.svg +0 -20
  63. package/dist/assets/img/caret.998eb8f.svg +0 -1
  64. package/dist/assets/img/convos_empty.2353007.svg +0 -72
  65. package/dist/assets/img/default.06e6ee0.jpg +0 -0
  66. package/dist/assets/img/default_avatar.5b74dc1.png +0 -0
  67. package/dist/assets/img/done_gray.d7e8203.svg +0 -4
  68. package/dist/assets/img/done_green.b817fd4.svg +0 -4
  69. package/dist/assets/img/emoji/messenger/sub_23.529_58.824.d5faf14.png +0 -0
  70. package/dist/assets/img/emoji/messenger/sub_23.529_60.784.1420241.png +0 -0
  71. package/dist/assets/img/emoji/messenger/sub_25.490_0.000.1e6b2c0.png +0 -0
  72. package/dist/assets/img/emoji/messenger/sub_25.490_45.098.3dfbc08.png +0 -0
  73. package/dist/assets/img/emoji/messenger/sub_25.490_5.882.4b49e94.png +0 -0
  74. package/dist/assets/img/emoji/messenger/sub_27.451_72.549.7114f58.png +0 -0
  75. package/dist/assets/img/emoji/messenger/sub_27.451_84.314.231e2b7.png +0 -0
  76. package/dist/assets/img/emoji/messenger/sub_27.451_96.078.ddbb008.png +0 -0
  77. package/dist/assets/img/emoji/messenger/sub_29.412_5.882.61f3359.png +0 -0
  78. package/dist/assets/img/emoji/messenger/sub_58.824_100.000.6df72bc.png +0 -0
  79. package/dist/assets/img/emoji/messenger/sub_58.824_45.098.3d7a7ad.png +0 -0
  80. package/dist/assets/img/emoji/messenger/sub_58.824_47.059.0f4d6e2.png +0 -0
  81. package/dist/assets/img/emoji/messenger/sub_58.824_54.902.65724c1.png +0 -0
  82. package/dist/assets/img/emoji/messenger/sub_58.824_64.706.9da3cba.png +0 -0
  83. package/dist/assets/img/emoji/messenger/sub_58.824_72.549.edca5cf.png +0 -0
  84. package/dist/assets/img/emoji/messenger/sub_58.824_78.431.f910f2a.png +0 -0
  85. package/dist/assets/img/emoji/messenger/sub_58.824_88.235.def4e71.png +0 -0
  86. package/dist/assets/img/emoji/messenger/sub_60.784_11.765.49c03d0.png +0 -0
  87. package/dist/assets/img/emoji/messenger/sub_60.784_27.451.46b54e5.png +0 -0
  88. package/dist/assets/img/emoji/messenger/sub_60.784_29.412.e36d284.png +0 -0
  89. package/dist/assets/img/emoji/messenger/sub_60.784_3.922.bb191b0.png +0 -0
  90. package/dist/assets/img/emoji/messenger/sub_60.784_35.294.af7b927.png +0 -0
  91. package/dist/assets/img/emoji/messenger/sub_60.784_7.843.98f2a99.png +0 -0
  92. package/dist/assets/img/empty.29bed2d.svg +0 -23
  93. package/dist/assets/img/empty_1.0b98af0.svg +0 -11
  94. package/dist/assets/img/examplte_logo.f86535f.svg +0 -1
  95. package/dist/assets/img/external-link.90577cc.svg +0 -1
  96. package/dist/assets/img/fb_inverse_circle.36c2cfc.png +0 -0
  97. package/dist/assets/img/ghn.070f8e3.svg +0 -17
  98. package/dist/assets/img/ghtk.326eac1.svg +0 -18
  99. package/dist/assets/img/image_default.be0698b.png +0 -0
  100. package/dist/assets/img/info.ebce7ea.svg +0 -1
  101. package/dist/assets/img/loader.37000a7.svg +0 -1
  102. package/dist/assets/img/loading_static.a27f0ac.svg +0 -10
  103. package/dist/assets/img/main-service1.d536cc2.png +0 -0
  104. package/dist/assets/img/main-service2.9b99549.png +0 -0
  105. package/dist/assets/img/not_found_search.2ddb8d1.png +0 -0
  106. package/dist/assets/img/package.8d37d0f.svg +0 -5
  107. package/dist/assets/img/package_fade.763c001.svg +0 -1
  108. package/dist/assets/img/rating--average.1ea492c.svg +0 -12
  109. package/dist/assets/img/rating--great.e3d712e.svg +0 -16
  110. package/dist/assets/img/rating--poor.2938a25.svg +0 -12
  111. package/dist/assets/img/search.f9705ff.svg +0 -1
  112. package/dist/assets/img/send.6db52a9.svg +0 -3
  113. package/dist/assets/img/shop.f7dc7d8.svg +0 -1
  114. package/dist/assets/img/shop_faded.df7845a.svg +0 -1
  115. package/dist/assets/img/subiz-mono.877e9f5.svg +0 -3
  116. package/dist/assets/img/x.26fdfa3.svg +0 -5
  117. package/dist/malicious-app.js +0 -15
  118. package/dist/screenshoot.html +0 -7
  119. package/dist/screenshoot.js +0 -10467
@@ -198,7 +198,7 @@ class Event extends _common.Com {
198
198
  onSelect: e => this.chooseQuickReply(e)
199
199
  }));
200
200
  }
201
- if (_index.default.getMsgField(ev, 'idempotency') === ev.id && this.props.store.now() - ev.created < 900) {
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.getMsgField(ev, 'idempotency') !== ev.id) {
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.getMsgField(newev, 'idempotency')) byme = true;
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
- fields: [{
278
- key: 'idempotency',
279
- value: '"wrueysyjbhqrkiwhsejpqrwqrdkkyaibajdw"'
280
- }],
277
+ idempotency_key: 'wrueysyjbhqrkiwhsejpqrwqrdkkyaibajdw',
281
278
  integration_id: inteid,
282
279
  pongs: [{
283
280
  member_id: userid,
@@ -175,6 +175,7 @@ class Store {
175
175
  this.fake = fakeapi;
176
176
  this.FileURL = FileURL;
177
177
  this._track_page_view = true;
178
+ this.device_type = 'desktop';
178
179
  if (this.fake) this.api = new _api_fake.default(ApiURL, FileURL);else this.api = new _api.default(ApiURL, FileURL);
179
180
  if (!inmem) {
180
181
  try {
@@ -195,15 +196,27 @@ class Store {
195
196
  this.chain = new _storage.default.chain(new _storage.default.lsdb('cbz2023', true), 'ch');
196
197
  this.getLocaleContent = this.api.getLocaleContent;
197
198
  this.g_haveSentSeenM = {};
198
- window.addEventListener('blur', this.sendPresence);
199
- window.addEventListener('focus', this.sendPresence);
199
+ this.last_focused = _index.default.Date.now();
200
+ window.addEventListener('blur', () => {
201
+ this.last_focused = _index.default.Date.now();
202
+ this.sendPresence();
203
+ });
204
+ window.addEventListener('focus', () => {
205
+ this.last_focused = 0;
206
+ this.sendPresence();
207
+ });
208
+ window.addEventListener('beforeunload', () => this.api.sendLostFocus());
200
209
  this._presenceInterval1 = _index.default.setInterval(() => {
201
210
  if (this._die) return _index.default.clearInterval(this._presenceInterval1);
202
211
  if (this.browserVisibility === 'visible' && document.hasFocus()) this.sendPresence();
203
212
  }, 20000);
204
213
  this._presenceInterval2 = _index.default.setInterval(() => {
205
214
  if (this._die) return _index.default.clearInterval(this._presenceInterval2);
206
- if (this.browserVisibility !== 'visible' || !document.hasFocus()) this.sendPresence();
215
+ if (this.browserVisibility === 'visible' && document.hasFocus()) return;
216
+ if (this.last_focused && _index.default.Date.now() - this.last_focused > 30 * 60000) {
217
+ return;
218
+ }
219
+ this.sendPresence();
207
220
  }, 60000);
208
221
  onVisibilityChange(val => {
209
222
  if (this._die) return;
@@ -281,12 +294,9 @@ class Store {
281
294
  }
282
295
  getDeviceInfo() {
283
296
  let device = {
284
- user_agent: window.navigator.userAgent,
285
297
  screen_resolution: window.screen.width + 'x' + window.screen.height,
286
298
  source_referrer: document.referrer,
287
299
  platform: window.navigator.platform,
288
- referrer: document.URL,
289
- type: this.isMobile() ? 'mobile' : 'desktop',
290
300
  language: navigator.language,
291
301
  page_url: document.URL,
292
302
  page_title: document.title
@@ -305,10 +315,10 @@ class Store {
305
315
  this.pubsub.publish('account');
306
316
  }
307
317
  isMobile() {
308
- return this.forceDevice === 'mobile' || mobileCheck;
318
+ return this.forceDevice === 'mobile' || this.device_type == 'mobile';
309
319
  }
310
320
  isTablet() {
311
- return this.forceDevice === 'tablet' || tabletCheck;
321
+ return this.forceDevice === 'tablet' || this.device_type == 'tablet';
312
322
  }
313
323
  isDesktop() {
314
324
  return this.forceDevice === 'desktop' || !this.isMobile() && !this.isTable();
@@ -436,7 +446,7 @@ class Store {
436
446
  var lastmsgsent = events[_index.default.size(events) - 1];
437
447
  if (!lastmsgsent) return;
438
448
  if (this.g_haveSentSeenM[lastmsgsent.id]) return;
439
- if (lastmsgsent.id === _index.default.getMsgField(lastmsgsent, 'idempotency')) return;
449
+ if (lastmsgsent.id === lastmsgsent.data.message.idempotency_key) return;
440
450
  this.api.markAsSeen(id, lastmsgsent.id);
441
451
  let convo = this.cache.match('convo_' + id) || {};
442
452
  let mem = _index.default.find(convo.members, m => m.id === user.id);
@@ -546,6 +556,7 @@ class Store {
546
556
  botM[bot.id] = bot;
547
557
  });
548
558
  this.cache.put('bot', botM);
559
+ this.device_type = setting.device_type || 'desktop';
549
560
  let plugins = _index.default.get(setting, 'plugins', []);
550
561
  let pluginM = {};
551
562
  _index.default.map(plugins, plugin => {
@@ -672,7 +683,7 @@ class Store {
672
683
  this.chain.put(cid, oldev.id, _index.default.getMs(oldev.created), oldev);
673
684
  }
674
685
  if (ev.type === 'message_sent') {
675
- let idemkey = _index.default.getMsgField(ev, 'idempotency');
686
+ let idemkey = _index.default.get(ev, 'data.message.idempotency_key');
676
687
  let found = _index.default.find(this.listEvents(cid), oldev => oldev.id === idemkey);
677
688
  if (found) {
678
689
  this.chain.del(cid, found.id);
@@ -739,7 +750,7 @@ class Store {
739
750
  _index.default.convoToEv(cid, event);
740
751
  let files = [];
741
752
  if (type === 'message_sent') {
742
- _index.default.setMsgField(event, 'idempotency', idempotency);
753
+ event.data.message.idempotency_key = idempotency;
743
754
  event.data.message.conversation_id = cid;
744
755
  await flow.map(event.data.message.attachments, 2, async (att, i) => {
745
756
  if (att.type !== 'file') return;
@@ -1076,10 +1087,6 @@ function sendEventToThirdParty(category, action, label) {
1076
1087
  event_label: label
1077
1088
  });
1078
1089
  }
1079
- let mobileCheck = function (a) {
1080
- return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4));
1081
- }(navigator.userAgent || navigator.vendor || window.opera);
1082
- let tabletCheck = /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(navigator.userAgent);
1083
1090
  let cleanLocalStorage = () => {
1084
1091
  try {
1085
1092
  localStorage;
@@ -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.replace('đ', 'd').replace('Đ', 'D');
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.73",
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.36.1",
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,17 +22,17 @@
22
22
  "preact": "10.19.3"
23
23
  },
24
24
  "devDependencies": {
25
- "@babel/cli": "^7.24.1",
26
- "@babel/core": "^7.24.4",
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.4",
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.6.3",
33
+ "puppeteer": "^22.7.1",
34
34
  "webpack": "^5.91.0",
35
- "webpack-bundle-analyzer": "^4.10.1",
35
+ "webpack-bundle-analyzer": "^4.10.2",
36
36
  "webpack-cli": "^5.1.4",
37
37
  "webpack-dev-server": "^5.0.4"
38
38
  }
@@ -185,14 +185,14 @@ export default class Event extends Com {
185
185
  )
186
186
  }
187
187
 
188
- if (sb.getMsgField(ev, 'idempotency') === ev.id && this.props.store.now() - ev.created < 900) {
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.getMsgField(ev, 'idempotency') !== ev.id) {
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
 
@@ -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.getMsgField(newev, 'idempotency')) byme = true
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()
@@ -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
- fields: [{key: 'idempotency', value: '"wrueysyjbhqrkiwhsejpqrwqrdkkyaibajdw"'}],
250
+ idempotency_key: 'wrueysyjbhqrkiwhsejpqrwqrdkkyaibajdw',
251
251
  integration_id: inteid,
252
252
  pongs: [{member_id: userid, type: 'seen', created: 1616213203068}],
253
253
  },
@@ -29,6 +29,7 @@ export default class Store {
29
29
  this.fake = fakeapi
30
30
  this.FileURL = FileURL
31
31
  this._track_page_view = true
32
+ this.device_type = 'desktop'
32
33
  if (this.fake) this.api = new APIFake(ApiURL, FileURL)
33
34
  else this.api = new API(ApiURL, FileURL)
34
35
 
@@ -57,9 +58,16 @@ export default class Store {
57
58
 
58
59
  // dont dupplicate seen
59
60
  this.g_haveSentSeenM = {}
60
-
61
- window.addEventListener('blur', this.sendPresence)
62
- window.addEventListener('focus', this.sendPresence)
61
+ this.last_focused = sb.Date.now() // 0 -> in focus, timestamp -> lost focus at
62
+ window.addEventListener('blur', () => {
63
+ this.last_focused = sb.Date.now()
64
+ this.sendPresence()
65
+ })
66
+ window.addEventListener('focus', () => {
67
+ this.last_focused = 0 //
68
+ this.sendPresence()
69
+ })
70
+ window.addEventListener('beforeunload', () => this.api.sendLostFocus())
63
71
 
64
72
  // faster send rate when has focus
65
73
  this._presenceInterval1 = sb.setInterval(() => {
@@ -69,7 +77,12 @@ export default class Store {
69
77
  // slower send rate send when user not focused
70
78
  this._presenceInterval2 = sb.setInterval(() => {
71
79
  if (this._die) return sb.clearInterval(this._presenceInterval2)
72
- if (this.browserVisibility !== 'visible' || !document.hasFocus()) this.sendPresence()
80
+ if (this.browserVisibility === 'visible' && document.hasFocus()) return
81
+ if (this.last_focused && sb.Date.now() - this.last_focused > 30 * 60000) {
82
+ // lost focus for more than 30 min
83
+ return // dont send presence
84
+ }
85
+ this.sendPresence()
73
86
  }, 60000) // dont bother delete this
74
87
 
75
88
  onVisibilityChange((val) => {
@@ -162,12 +175,9 @@ export default class Store {
162
175
 
163
176
  getDeviceInfo() {
164
177
  let device = {
165
- user_agent: window.navigator.userAgent,
166
178
  screen_resolution: window.screen.width + 'x' + window.screen.height,
167
179
  source_referrer: document.referrer,
168
180
  platform: window.navigator.platform,
169
- referrer: document.URL,
170
- type: this.isMobile() ? 'mobile' : 'desktop',
171
181
  language: navigator.language,
172
182
  page_url: document.URL,
173
183
  page_title: document.title,
@@ -192,11 +202,11 @@ export default class Store {
192
202
  }
193
203
 
194
204
  isMobile() {
195
- return this.forceDevice === 'mobile' || mobileCheck
205
+ return this.forceDevice === 'mobile' || this.device_type == 'mobile'
196
206
  }
197
207
 
198
208
  isTablet() {
199
- return this.forceDevice === 'tablet' || tabletCheck
209
+ return this.forceDevice === 'tablet' || this.device_type == 'tablet'
200
210
  }
201
211
 
202
212
  isDesktop() {
@@ -495,7 +505,7 @@ export default class Store {
495
505
  if (this.g_haveSentSeenM[lastmsgsent.id]) return
496
506
 
497
507
  // ignore sending message
498
- if (lastmsgsent.id === sb.getMsgField(lastmsgsent, 'idempotency')) return
508
+ if (lastmsgsent.id === lastmsgsent.data.message.idempotency_key) return
499
509
 
500
510
  // send seen
501
511
  this.api.markAsSeen(id, lastmsgsent.id)
@@ -647,7 +657,7 @@ export default class Store {
647
657
  botM[bot.id] = bot
648
658
  })
649
659
  this.cache.put('bot', botM)
650
-
660
+ this.device_type = setting.device_type || 'desktop'
651
661
  // web plugin
652
662
  let plugins = sb.get(setting, 'plugins', [])
653
663
  let pluginM = {}
@@ -803,7 +813,7 @@ export default class Store {
803
813
  }
804
814
 
805
815
  if (ev.type === 'message_sent') {
806
- let idemkey = sb.getMsgField(ev, 'idempotency')
816
+ let idemkey = sb.get(ev, 'data.message.idempotency_key')
807
817
  let found = sb.find(this.listEvents(cid), (oldev) => oldev.id === idemkey)
808
818
  if (found) {
809
819
  // keeping old created so the ui can be static
@@ -874,7 +884,7 @@ export default class Store {
874
884
  sb.convoToEv(cid, event)
875
885
  let files = []
876
886
  if (type === 'message_sent') {
877
- sb.setMsgField(event, 'idempotency', idempotency)
887
+ event.data.message.idempotency_key = idempotency
878
888
  event.data.message.conversation_id = cid
879
889
 
880
890
  // pre upload image files
@@ -1259,23 +1269,6 @@ function sendEventToThirdParty(category, action, label) {
1259
1269
  dataLayer.push({event: category, event_action: action, event_label: label})
1260
1270
  }
1261
1271
 
1262
- // from http://detectmobilebrowsers.com/
1263
- let mobileCheck = (function (a) {
1264
- return (
1265
- /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
1266
- a,
1267
- ) ||
1268
- /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
1269
- a.substr(0, 4),
1270
- )
1271
- )
1272
- })(navigator.userAgent || navigator.vendor || window.opera)
1273
-
1274
- let tabletCheck =
1275
- /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(
1276
- navigator.userAgent,
1277
- )
1278
-
1279
1272
  let cleanLocalStorage = () => {
1280
1273
  try {
1281
1274
  localStorage
@@ -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.replace('đ', 'd').replace('Đ', 'D')
1100
+ str = str.replaceAll('đ', 'd').replaceAll('Đ', 'D')
1128
1101
  return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
1129
1102
  }
1130
1103