@subiz/widget-v4 4.1.15 → 4.1.16

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.
@@ -12,6 +12,13 @@
12
12
  flex: 1;
13
13
  }
14
14
 
15
+ .mobile .widget-body--events {
16
+ display: flex;
17
+ flex-direction: column;
18
+ justify-content: flex-end;
19
+ padding-bottom: 15px;
20
+ }
21
+
15
22
  .widget-body--events-container.widget-body--events-container__error {
16
23
  align-items: center;
17
24
  justify-content: center;
@@ -850,7 +850,8 @@ class Popup extends _common.Com {
850
850
  background: pagestyle.background || popup.background || '#fff',
851
851
  border: pagestyle.border,
852
852
  overflow: layout === 'row' ? 'auto' : '',
853
- max_height: layout === 'row' ? '100%' : ''
853
+ max_height: layout === 'row' ? '100%' : '',
854
+ min_height: layout === 'row' ? '100%' : ''
854
855
  };
855
856
  let bodycss = {
856
857
  overflow: layout === 'column' ? 'auto' : '',
@@ -29,7 +29,7 @@ class Store {
29
29
  _defineProperty(this, "new_visitor", true);
30
30
  _defineProperty(this, "matchUser", () => {
31
31
  this._touchAcc();
32
- return this.kv.match('user');
32
+ return this.cache.match('user');
33
33
  });
34
34
  _defineProperty(this, "suggest_addresses", keyword => this.api.suggest_address(keyword));
35
35
  _defineProperty(this, "matchAccount", () => this.cache.match('account'));
@@ -82,7 +82,7 @@ class Store {
82
82
  _defineProperty(this, "listEvents", id => {
83
83
  if (!id || id === '*' || typeof id !== 'string') return;
84
84
  if (!this.isInsync('events' + id)) {
85
- setTimeout(async () => {
85
+ _index.default.setTimeout(async () => {
86
86
  await this.readyGate.entry();
87
87
  await this.reconnectGate.entry(undefined, true);
88
88
  if (this.isInsync('events' + id)) return this.reconnectGate.open();
@@ -109,14 +109,20 @@ class Store {
109
109
  _defineProperty(this, "convoGate", new _index.default.Gate(true));
110
110
  _defineProperty(this, "reconnectGate", new _index.default.Gate(true));
111
111
  _defineProperty(this, "wsGate", new _index.default.Gate(true));
112
- _defineProperty(this, "matchLastview", () => this.kv.match('lastview') || {});
112
+ _defineProperty(this, "matchLastview", () => {
113
+ let lastView = this.kv.match('lastview') || {};
114
+ let user = this.cache.match('user') || {};
115
+ if (!user.id) return {};
116
+ if (lastView.user_id != user.id) return {};
117
+ return lastView;
118
+ });
113
119
  _defineProperty(this, "matchIsOpen", () => !!this.kv.match('isopen'));
114
120
  _defineProperty(this, "matchHasManuallyClosed", () => !!this.kv.match('hasManuallyClosed'));
115
121
  _defineProperty(this, "matchClosePreviewAt", () => this.kv.match('close_preview_at') || 0);
116
122
  _defineProperty(this, "sendPresence", _index.default.throttle(async () => {
117
123
  await this.readyGate.entry();
118
- if (!_index.default.get(this.kv.match('user'), 'id')) return;
119
- if (_index.default.isUserBanned(this.kv.match('user'))) return;
124
+ if (!_index.default.get(this.cache.match('user'), 'id')) return;
125
+ if (_index.default.isUserBanned(this.cache.match('user'))) return;
120
126
  let hasfocus = this.browserVisibility === 'visible' && document.hasFocus();
121
127
  if (!hasfocus) {
122
128
  this.api.sendLostFocus(this.device, this._currentViewingProduct.id, this._currentViewingProduct.source_id, this._currentViewingProduct.sku);
@@ -149,10 +155,15 @@ class Store {
149
155
  }
150
156
  });
151
157
  _defineProperty(this, "closePreview", () => this.kv.put('close_preview_at', new _index.default.Date().getTime()));
152
- _defineProperty(this, "setLastview", (view, opts) => this.kv.put('lastview', {
153
- view,
154
- opts
155
- }));
158
+ _defineProperty(this, "setLastview", (view, opts) => {
159
+ let user = this.cache.match('user') || {};
160
+ if (!user.id) return;
161
+ this.kv.put('lastview', {
162
+ user_id: user.id,
163
+ view,
164
+ opts
165
+ });
166
+ });
156
167
  _defineProperty(this, "timeDiff", 0);
157
168
  this.g_sync = {};
158
169
  this.forceDevice = null;
@@ -175,24 +186,25 @@ class Store {
175
186
  this.inmem = inmem;
176
187
  this.cookie = inmemCookie;
177
188
  }
189
+ cleanLocalStorage();
178
190
  this.pubsub = new _index.default.Pubsub();
179
- this.kv = new _storage.default.kv(new _storage.default.lsdb('sbz2020', this.inmem), 'kv');
180
- this.cache = new _storage.default.kv(new _storage.default.lsdb('sbz2020', true), 'kv');
181
- this.chain = new _storage.default.chain(new _storage.default.lsdb('cbz2020', true), 'ch');
191
+ this.kv = new _storage.default.kv(new _storage.default.lsdb('sbz2023', this.inmem), 'kv');
192
+ this.cache = new _storage.default.kv(new _storage.default.lsdb('sbz2023', true), 'kv');
193
+ this.chain = new _storage.default.chain(new _storage.default.lsdb('cbz2023', true), 'ch');
182
194
  this.getLocaleContent = this.api.getLocaleContent;
183
195
  this.g_haveSentSeenM = {};
184
196
  window.addEventListener('blur', () => this.sendPresence());
185
197
  window.addEventListener('focus', () => this.sendPresence());
186
- setInterval(() => this.browserVisibility === 'visible' && document.hasFocus() && this.sendPresence(), 20000);
187
- setInterval(() => (this.browserVisibility !== 'visible' || document.hasFocus()) && this.sendPresence(), 60000);
198
+ _index.default.setInterval(() => this.browserVisibility === 'visible' && document.hasFocus() && this.sendPresence(), 20000);
199
+ _index.default.setInterval(() => (this.browserVisibility !== 'visible' || document.hasFocus()) && this.sendPresence(), 60000);
188
200
  onVisibilityChange(val => {
189
201
  this.browserVisibility = val;
190
202
  this.sendPresence();
191
203
  });
192
204
  this.loopTime();
193
205
  this.device = this.getDeviceInfo();
194
- const _gaInterval = setInterval(() => {
195
- let user = this.kv.match('user') || {};
206
+ const _gaInterval = _index.default.setInterval(() => {
207
+ let user = this.cache.match('user') || {};
196
208
  if (!user.id) return;
197
209
  var dev = this.getDeviceInfo();
198
210
  if (!dev.ga_tracking_ids || !dev.ga_client_id) return;
@@ -250,7 +262,7 @@ class Store {
250
262
  await this.readyGate.entry();
251
263
  this.disconnect('account');
252
264
  await this.reconnect();
253
- setTimeout(this.pubsub.publish('resetCSS'), 10);
265
+ _index.default.setTimeout(this.pubsub.publish('resetCSS'), 10);
254
266
  }
255
267
  getDeviceInfo() {
256
268
  let device = {
@@ -394,9 +406,9 @@ class Store {
394
406
  seenLoop() {
395
407
  this.seenQueue = [];
396
408
  clearInterval(this._seenInterval);
397
- this._seenInterval = setInterval(() => {
409
+ this._seenInterval = _index.default.setInterval(() => {
398
410
  this.seenQueue = [...new Set(this.seenQueue)];
399
- let user = this.kv.match('user') || {};
411
+ let user = this.cache.match('user') || {};
400
412
  _index.default.map(this.seenQueue, id => {
401
413
  var events = this.listEvents(id);
402
414
  if (!events) return;
@@ -455,7 +467,7 @@ class Store {
455
467
  }
456
468
  _setUser(user) {
457
469
  user = _index.default.cloneDeep(user);
458
- let olduser = this.kv.match('user') || {};
470
+ let olduser = this.cache.match('user') || {};
459
471
  var accid = olduser.account_id || user.account_id;
460
472
  var id = olduser.id || user.id;
461
473
  _index.default.each(user.attributes, newattr => {
@@ -469,7 +481,7 @@ class Store {
469
481
  olduser.attributes = olduser.attributes.concat(user.attributes);
470
482
  olduser.account_id = accid;
471
483
  olduser.id = id;
472
- this.kv.put('user', olduser);
484
+ this.cache.put('user', olduser);
473
485
  this.pubsub.publish('account');
474
486
  }
475
487
  async setSetting(setting) {
@@ -539,13 +551,13 @@ class Store {
539
551
  if (!ev || !ev.type) return;
540
552
  ev.created = _index.default.getMs(ev.created);
541
553
  if (ev.type === 'user_info_updated') {
542
- let user = _index.default.cloneDeep(this.kv.match('user'));
554
+ let user = _index.default.cloneDeep(this.cache.match('user'));
543
555
  let attrs = _index.default.get(ev, 'data.user.attributes') || [];
544
556
  _index.default.map(attrs, attr => _index.default.setUserAttr(user, attr));
545
557
  this._setUser(user);
546
558
  return;
547
559
  }
548
- let user = this.kv.match('user') || {};
560
+ let user = this.cache.match('user') || {};
549
561
  let cid = _index.default.convoOfEv(ev);
550
562
  let convo;
551
563
  let alreadyFetched = false;
@@ -568,7 +580,7 @@ class Store {
568
580
  this.pubsub.publish('events', ev);
569
581
  if (ev.type === 'conversation_joined') {
570
582
  let members = _index.default.get(ev, 'data.conversation.members', []);
571
- let me = _index.default.find(members, m => m.id === this.kv.match('user').id);
583
+ let me = _index.default.find(members, m => m.id === this.cache.match('user').id);
572
584
  if (me) {
573
585
  await this.chain.reload(cid, (type, anchor, limit) => this.listmessageapi(type, anchor, limit));
574
586
  this.markSync('events' + cid);
@@ -598,7 +610,7 @@ class Store {
598
610
  }
599
611
  }
600
612
  async restConvoEvent(ev) {
601
- let user = this.kv.match('user');
613
+ let user = this.cache.match('user');
602
614
  let cid = _index.default.convoOfEv(ev);
603
615
  let convo = this.cache.match('convo_' + cid) || {};
604
616
  if (ev.type === 'conversation_state_updated') {
@@ -704,7 +716,7 @@ class Store {
704
716
  async sendConvoEvent(cid, type, data) {
705
717
  await this.readyGate.entry();
706
718
  var idempotency = _index.default.randomString(36);
707
- let user = this.kv.match('user') || {};
719
+ let user = this.cache.match('user') || {};
708
720
  var event = {
709
721
  id: idempotency,
710
722
  by: {
@@ -767,7 +779,7 @@ class Store {
767
779
  }
768
780
  _setConvo(convo) {
769
781
  let count = 0;
770
- let user = this.kv.match('user');
782
+ let user = this.cache.match('user');
771
783
  let channel = _index.default.get(convo, 'touchpoint.channel', '');
772
784
  if (channel && channel != 'subiz') return;
773
785
  let allconvo = {};
@@ -804,7 +816,7 @@ class Store {
804
816
  this.kv.put('bot_run_logs', log);
805
817
  }
806
818
  sendImpression(id) {
807
- let user = this.kv.match('user') || {};
819
+ let user = this.cache.match('user') || {};
808
820
  let log = this.kv.match('plugin_run_logs') || {};
809
821
  log[id] = {
810
822
  web_plugin_id: id,
@@ -821,7 +833,7 @@ class Store {
821
833
  });
822
834
  }
823
835
  sendConversion(id, fields, impressionToken) {
824
- let user = this.kv.match('user') || {};
836
+ let user = this.cache.match('user') || {};
825
837
  let submission = {
826
838
  account_id: user.account_id,
827
839
  user_id: user.id,
@@ -862,7 +874,7 @@ class Store {
862
874
  value: event
863
875
  };
864
876
  });
865
- let user = this.kv.match('user') || {};
877
+ let user = this.cache.match('user') || {};
866
878
  for (let i = 0; i < events.length; i++) {
867
879
  let ev = events[i].value;
868
880
  if (ev.type !== 'message_sent') continue;
@@ -876,17 +888,17 @@ class Store {
876
888
  }
877
889
  async loopTime() {
878
890
  let startms = _index.default.Date.now();
879
- if (!_index.default.get(this.kv.match('user'), 'id')) return setTimeout(() => this.loopTime(), 240000);
891
+ if (!_index.default.get(this.cache.match('user'), 'id')) return _index.default.setTimeout(() => this.loopTime(), 240000);
880
892
  let {
881
893
  body: t,
882
894
  error
883
895
  } = await this.api.time();
884
- if (error) return setTimeout(() => this.loopTime(), 30000);
896
+ if (error) return _index.default.setTimeout(() => this.loopTime(), 30000);
885
897
  var latences = Math.abs(_index.default.Date.now() - startms) / 2;
886
898
  var serverMs = new _index.default.Date(t).getTime() + latences;
887
899
  var localMs = _index.default.Date.now();
888
900
  this.timeDiff = Math.floor(serverMs - localMs);
889
- setTimeout(() => this.loopTime(), 240000);
901
+ _index.default.setTimeout(() => this.loopTime(), 240000);
890
902
  }
891
903
  replaceFileUrl(src) {
892
904
  if (!src) return '';
@@ -914,9 +926,9 @@ class Store {
914
926
  if ((k || '').startsWith('__sb')) this.cookie.remove(k);
915
927
  });
916
928
  this.kv.destroy();
917
- this.kv = new _storage.default.kv(new _storage.default.lsdb('sbz2020', this.inmem), 'kv');
929
+ this.kv = new _storage.default.kv(new _storage.default.lsdb('sbz2023', this.inmem), 'kv');
918
930
  this.chain.destroy();
919
- this.chain = new _storage.default.chain(new _storage.default.lsdb('cbz2020', true), 'ch');
931
+ this.chain = new _storage.default.chain(new _storage.default.lsdb('cbz2023', true), 'ch');
920
932
  }
921
933
  destroy() {
922
934
  this._die = true;
@@ -1034,4 +1046,18 @@ function sendEventToThirdParty(category, action, label) {
1034
1046
  let mobileCheck = function (a) {
1035
1047
  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));
1036
1048
  }(navigator.userAgent || navigator.vendor || window.opera);
1037
- let tabletCheck = /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(navigator.userAgent);
1049
+ let tabletCheck = /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(navigator.userAgent);
1050
+ let cleanLocalStorage = () => {
1051
+ try {
1052
+ localStorage;
1053
+ } catch (e) {
1054
+ return;
1055
+ }
1056
+ _index.default.setTimeout(() => {
1057
+ for (var key in localStorage) {
1058
+ if (key && (key.startsWith('cbz2020') || key.startsWith('sbz2020'))) {
1059
+ localStorage.removeItem(key);
1060
+ }
1061
+ }
1062
+ });
1063
+ };
@@ -80,9 +80,9 @@ var Date = f.contentWindow.Date;
80
80
  exports.Date = Date;
81
81
  var requestAnimationFrame = f.contentWindow.requestAnimationFrame;
82
82
  exports.requestAnimationFrame = requestAnimationFrame;
83
- var setTimeout = f.contentWindow.setTimeout;
83
+ var setTimeout = f.contentWindow.setTimeout.bind(f.contentWindow);
84
84
  exports.setTimeout = setTimeout;
85
- var setInterval = f.contentWindow.setInterval;
85
+ var setInterval = f.contentWindow.setInterval.bind(f.contentWindow);
86
86
  exports.setInterval = setInterval;
87
87
  function convoOfEv(ev) {
88
88
  if (!ev) return '';
package/inject.js CHANGED
@@ -13,13 +13,14 @@ function getUrlParameter(name) {
13
13
  function runChatbox(subiz) {
14
14
  let popup = {
15
15
  account_id: 'acqsulrowbxiugvginhw',
16
- id: 'cprolocggdxtgbzrdtvkp',
17
- name: 'Lì xì đầu năm',
16
+ id: 'cpropvrepsupxyuqcxsqu',
17
+ name: 'Khuyến mãi xe hơi',
18
18
  type: 'popup',
19
- created: 1675306404915,
19
+ created: 1675912199122,
20
20
  created_by: 'agqsulrowbxilyzhds',
21
- updated: 1675307604095,
21
+ updated: 1675912207092,
22
22
  updated_by: 'agqsulrowbxilyzhds',
23
+ enabled: true,
23
24
  triggers: [
24
25
  {
25
26
  type: 'after_pageview',
@@ -36,60 +37,42 @@ function runChatbox(subiz) {
36
37
  animation: true,
37
38
  show_close_button: true,
38
39
  overlay: true,
39
- text_color: '#333',
40
+ text_color: 'rgba(0,0,0,1)',
40
41
  font_family: 'Roboto',
41
- font_size: '16px',
42
+ font_size: '14px',
42
43
  background: 'white',
43
44
  spacer: '10',
44
- theme: 'bold',
45
+ theme: 'classic',
45
46
  pages: [
46
47
  {
47
48
  components: [
48
- {
49
- type: 'image',
50
- style: {
51
- background_position: '0% 100%',
52
- left: '0px',
53
- right: '0px',
54
- top: '0px',
55
- bottom: '0px',
56
- },
57
- mobile_style: {
58
- background_position: '0% 100%',
59
- left: '0px',
60
- right: '0px',
61
- top: '0px',
62
- bottom: '0px',
63
- },
64
- image: {
65
- url: 'https://vcdn.subiz-cdn.com/file/firobdruwymdykrgoikj-10.png',
66
- },
67
- },
68
49
  {
69
50
  type: 'text',
70
51
  style: {
71
- font_family: 'Dancing Script',
72
- color: 'rgba(207,32,47,1)',
52
+ font_family: 'Yeseva One',
53
+ color: 'rgba(208,2,27,1)',
54
+ background: 'rgba(0,0,0,0)',
73
55
  text_align: 'center',
74
56
  font_style: 'normal',
75
57
  font_weight: 'bold',
76
58
  margin_bottom: '20px',
77
- font_size: '72px',
59
+ font_size: '30px',
78
60
  },
79
61
  mobile_style: {
80
- font_family: 'Dancing Script',
81
- color: 'rgba(207,32,47,1)',
62
+ font_family: 'Yeseva One',
63
+ color: 'rgba(208,2,27,1)',
64
+ background: 'rgba(0,0,0,0)',
82
65
  text_align: 'center',
83
66
  font_style: 'normal',
84
67
  font_weight: 'bold',
85
- margin_bottom: '10px',
86
- font_size: '14px',
68
+ margin_bottom: '20px',
69
+ font_size: '20px',
87
70
  },
88
71
  text: {
89
- html: 'Đăng ký nhận ưu đãi khủng',
72
+ html: 'CƠ HỘI TRONG TAY\nRINH NGAY XẾ XỊN',
90
73
  i18n_html: {
91
- en_US: 'Lì xì đầu năm',
92
- vi_VN: 'Lì xì đầu năm',
74
+ en_US: 'CƠ HỘI TRONG TAY\nRINH NGAY XẾ XỊN',
75
+ vi_VN: 'CƠ HỘI TRONG TAY\nRINH NGAY XẾ XỊN',
93
76
  },
94
77
  i18n_quill_delta: {},
95
78
  },
@@ -97,54 +80,86 @@ function runChatbox(subiz) {
97
80
  {
98
81
  type: 'text',
99
82
  style: {
100
- font_family: 'Montserrat',
101
83
  text_align: 'center',
102
- font_style: 'normal',
84
+ font_style: 'italic',
103
85
  font_weight: 'normal',
104
86
  margin_bottom: '20px',
105
- font_size: '20px',
87
+ font_size: '16px',
106
88
  },
107
89
  mobile_style: {
108
- font_family: 'Montserrat',
109
90
  text_align: 'center',
110
- font_style: 'normal',
91
+ font_style: 'italic',
111
92
  font_weight: 'normal',
112
- margin_bottom: '10px',
113
- font_size: '10px',
114
93
  },
115
94
  text: {
116
- html: 'Giảm giá tới 95%\nMiễn phí vận chuyển nội thành',
95
+ html: 'Lãi suất ưu đãi - Hỗ trợ trả góp 90%\nCùng dịch vụ hậu mãi đẳng cấp đi kèm nhiều phần quà hấp dẫn khác',
117
96
  i18n_html: {
118
97
  en_US:
119
- 'Mừng xuân mới, tặng ngay bao lì xì \nmệnh giá 100.000 đến 500.000 VND \ncho 50 đơn hàng đầu tiên',
98
+ 'Lãi suất ưu đãi - Hỗ trợ trả góp 90%\nCùng dịch vụ hậu mãi đẳng cấp đi kèm nhiều phần quà hấp dẫn khác',
120
99
  vi_VN:
121
- 'Mừng xuân mới, tặng ngay bao lì xì \nmệnh giá 100.000 đến 500.000 VND \ncho 50 đơn hàng đầu tiên',
100
+ 'Lãi suất ưu đãi - Hỗ trợ trả góp 90%\nCùng dịch vụ hậu mãi đẳng cấp đi kèm nhiều phần quà hấp dẫn khác',
122
101
  },
123
102
  i18n_quill_delta: {},
124
103
  },
125
104
  },
105
+ {
106
+ type: 'form',
107
+ style: {
108
+ margin_bottom: '20px',
109
+ },
110
+ form: {
111
+ fields: [
112
+ {
113
+ key: 'email',
114
+ label: 'Email',
115
+ i18n_label: {
116
+ en_US: 'Email',
117
+ vi_VN: 'Email',
118
+ },
119
+ is_required: true,
120
+ type: 'email',
121
+ validate: 'email',
122
+ placeholder: 'abc@example.com',
123
+ i18n_placeholder: {
124
+ en_US: 'abc@example.com',
125
+ vi_VN: 'abc@example.com',
126
+ },
127
+ },
128
+ {
129
+ key: 'phone',
130
+ label: 'Số điện thoại',
131
+ i18n_label: {
132
+ en_US: 'Số điện thoại',
133
+ vi_VN: 'Số điện thoại',
134
+ },
135
+ is_required: true,
136
+ type: 'text',
137
+ validate: 'phone',
138
+ placeholder: '036123456',
139
+ i18n_placeholder: {
140
+ en_US: '036123456',
141
+ vi_VN: '036123456',
142
+ },
143
+ },
144
+ ],
145
+ },
146
+ },
126
147
  {
127
148
  type: 'buttons',
128
149
  style: {
129
150
  border_radius: '12px',
130
- background: 'rgba(207,32,47,1)',
151
+ background: 'rgba(174,0,0,1)',
131
152
  flex_direction: 'column',
132
- },
133
- mobile_style: {
134
- font_size: '10px',
135
- padding_top: '5px',
136
- padding_bottom: '5px',
153
+ align_items: 'center',
137
154
  },
138
155
  buttons: {
139
156
  primary_enabled: true,
140
157
  primary_actions: [
141
158
  {
142
- action: 'open_url',
143
- url: 'https://subiz.com.vn',
144
- new_tab: true,
159
+ action: 'conversion',
145
160
  },
146
161
  {
147
- action: 'close',
162
+ action: 'next_page',
148
163
  },
149
164
  ],
150
165
  primary_text: 'Đăng ký ngay',
@@ -158,41 +173,59 @@ function runChatbox(subiz) {
158
173
  },
159
174
  ],
160
175
  i18n_secondary_text: {
161
- en_US: 'Cancel',
162
176
  vi_VN: 'Đăng ký ngay',
163
177
  },
164
178
  },
165
179
  },
180
+ {
181
+ type: 'image',
182
+ style: {
183
+ width: '375px',
184
+ height: '100%',
185
+ background_position: '28.711790393013125% 0%',
186
+ right: '0',
187
+ top: '0',
188
+ },
189
+ mobile_style: {
190
+ width: '100%',
191
+ height: '150px',
192
+ background_position: '0% 51.66666666666666%',
193
+ left: '0',
194
+ top: '0',
195
+ },
196
+ image: {
197
+ url: 'https://images.unsplash.com/photo-1606220838315-056192d5e927?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMjA3fDB8MXxzZWFyY2h8NDJ8fGNhciUzRCUzRCUzRCUzRCUzRCUzRCUzRHxlbnwwfHx8fDE2MjAzNjA3NDc&ixlib=rb-1.2.1&q=80&w=1080',
198
+ },
199
+ },
166
200
  ],
167
201
  style: {
168
- background: 'rgba(255,255,255,0)',
169
- width: '800px',
170
- height: '565px',
202
+ background: 'rgba(255,255,255,1)',
203
+ width: '751px',
204
+ height: 'auto',
171
205
  padding_left: '40px',
172
206
  padding_right: '40px',
173
207
  padding_top: '40px',
174
208
  padding_bottom: '40px',
175
- margin_left: '150px',
176
- margin_right: '150px',
177
- margin_top: '120px',
178
- margin_bottom: '120px',
209
+ margin_left: '0px',
210
+ margin_right: '375px',
211
+ margin_top: '0px',
212
+ margin_bottom: '0px',
179
213
  overflow: 'hidden',
180
214
  },
181
215
  mobile_style: {
182
- background: 'rgba(255,255,255,0)',
183
- width: '300px',
184
- height: '200px',
216
+ background: 'rgba(255,255,255,1)',
217
+ width: '400px',
185
218
  padding_left: '40px',
186
219
  padding_right: '40px',
187
220
  padding_top: '40px',
188
221
  padding_bottom: '40px',
189
222
  margin_left: '0px',
190
223
  margin_right: '0px',
191
- margin_top: '0px',
224
+ margin_top: '149px',
192
225
  margin_bottom: '0px',
193
226
  },
194
227
  layout: 'row',
195
- mobile_layout: 'row',
228
+ mobile_layout: 'column',
196
229
  },
197
230
  {
198
231
  components: [
@@ -211,8 +244,8 @@ function runChatbox(subiz) {
211
244
  text: {
212
245
  html: 'Cảm ơn',
213
246
  i18n_html: {
214
- en_US: 'Thank you',
215
- vi_VN: 'Thank you',
247
+ en_US: 'Cảm ơn',
248
+ vi_VN: 'Cảm ơn',
216
249
  },
217
250
  i18n_quill_delta: {},
218
251
  },
@@ -227,8 +260,8 @@ function runChatbox(subiz) {
227
260
  text: {
228
261
  html: 'Chúng tôi đã ghi nhận được yêu cầu của bạn',
229
262
  i18n_html: {
230
- en_US: 'We had received your request',
231
- vi_VN: 'We had received your request',
263
+ en_US: 'Chúng tôi đã ghi nhận được yêu cầu của bạn',
264
+ vi_VN: 'Chúng tôi đã ghi nhận được yêu cầu của bạn',
232
265
  },
233
266
  i18n_quill_delta: {},
234
267
  },
@@ -252,16 +285,17 @@ function runChatbox(subiz) {
252
285
  ],
253
286
  primary_text: 'Đóng',
254
287
  i18n_primary_text: {
255
- en_US: 'Close',
256
- vi_VN: 'Close',
288
+ en_US: 'Đóng',
289
+ vi_VN: 'Đóng',
257
290
  },
258
291
  i18n_secondary_text: {
259
- vi_VN: 'Close',
292
+ vi_VN: 'Đóng',
260
293
  },
261
294
  },
262
295
  },
263
296
  ],
264
297
  style: {
298
+ background: '#fff',
265
299
  width: '300px',
266
300
  padding_left: '40px',
267
301
  padding_right: '40px',
@@ -270,6 +304,7 @@ function runChatbox(subiz) {
270
304
  overflow: 'hidden',
271
305
  },
272
306
  mobile_style: {
307
+ background: '#fff',
273
308
  width: '300px',
274
309
  padding_left: '40px',
275
310
  padding_right: '40px',
@@ -282,13 +317,11 @@ function runChatbox(subiz) {
282
317
  conversion_notification: {
283
318
  all_agents: true,
284
319
  },
285
- template_categories: ['Năm mới'],
286
- template_title: 'Lì xì đầu năm',
287
- thumbnail_url:
288
- 'https://vcdn.subiz-cdn.com/file/firobhhkwjwiirovikuh-firobhhkfosiufzphxicwptp1673839749423clmwirrp.jpg',
320
+ template_categories: ['Xe hơi'],
321
+ template_title: 'Khuyến mãi xe hơi',
322
+ thumbnail_url: 'https://file-subiz.com/fiqzycspqbycpbawhjzbwptpkufqxwin.jpg',
289
323
  }
290
324
  subiz._overridePlugin([popup])
291
- console.log('GGGGGGG', popup)
292
325
 
293
326
  setTimeout(() => {
294
327
  subiz.showWidget()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subiz/widget-v4",
3
- "version": "4.1.15",
3
+ "version": "4.1.16",
4
4
  "main": "./compiled_src/lib.js",
5
5
  "scripts": {
6
6
  "dev": "npx webpack serve --config webpack.dev.js",
@@ -14,25 +14,25 @@
14
14
  "@subiz/storage": "0.0.8",
15
15
  "@subiz/wsclient": "^3.1.9",
16
16
  "cookie_js": "1.4.2",
17
- "core-js": "^3.27.0",
17
+ "core-js": "^3.27.2",
18
18
  "css-loader": "5.2.7",
19
19
  "file-loader": "^6.2.0",
20
20
  "less": "^4.1.3",
21
21
  "less-loader": "^11.1.0",
22
- "marked": "^4.2.5",
22
+ "marked": "^4.2.12",
23
23
  "preact": "^10.11.3"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@babel/cli": "^7.20.7",
27
- "@babel/core": "^7.20.7",
27
+ "@babel/core": "^7.20.12",
28
28
  "@babel/plugin-proposal-class-properties": "^7.18.6",
29
- "@babel/plugin-transform-react-jsx": "^7.20.7",
29
+ "@babel/plugin-transform-react-jsx": "^7.20.13",
30
30
  "@babel/preset-env": "^7.20.2",
31
- "babel-loader": "^9.1.0",
31
+ "babel-loader": "^9.1.2",
32
32
  "babel-plugin-syntax-jsx": "^6.18.0",
33
33
  "html-webpack-plugin": "^5.5.0",
34
- "prettier": "^2.8.1",
35
- "puppeteer": "^19.4.1",
34
+ "prettier": "^2.8.3",
35
+ "puppeteer": "^19.6.3",
36
36
  "webpack": "^5.75.0",
37
37
  "webpack-bundle-analyzer": "^4.7.0",
38
38
  "webpack-cli": "^5.0.1",
@@ -927,6 +927,7 @@ export default class Popup extends Com {
927
927
  border: pagestyle.border,
928
928
  overflow: layout === 'row' ? 'auto' : '',
929
929
  max_height: layout === 'row' ? '100%' : '',
930
+ min_height: layout === 'row' ? '100%' : '',
930
931
  }
931
932
  let bodycss = {
932
933
  overflow: layout === 'column' ? 'auto' : '',
@@ -47,10 +47,11 @@ export default class Store {
47
47
  this.cookie = inmemCookie
48
48
  }
49
49
 
50
+ cleanLocalStorage()
50
51
  this.pubsub = new sb.Pubsub()
51
- this.kv = new stor8.kv(new stor8.lsdb('sbz2020', this.inmem), 'kv')
52
- this.cache = new stor8.kv(new stor8.lsdb('sbz2020', true), 'kv')
53
- this.chain = new stor8.chain(new stor8.lsdb('cbz2020', true), 'ch')
52
+ this.kv = new stor8.kv(new stor8.lsdb('sbz2023', this.inmem), 'kv')
53
+ this.cache = new stor8.kv(new stor8.lsdb('sbz2023', true), 'kv')
54
+ this.chain = new stor8.chain(new stor8.lsdb('cbz2023', true), 'ch')
54
55
  this.getLocaleContent = this.api.getLocaleContent
55
56
 
56
57
  // dont dupplicate seen
@@ -60,9 +61,9 @@ export default class Store {
60
61
  window.addEventListener('focus', () => this.sendPresence())
61
62
 
62
63
  // faster send rate when has focus
63
- setInterval(() => this.browserVisibility === 'visible' && document.hasFocus() && this.sendPresence(), 20000) // dont bother delete this
64
+ sb.setInterval(() => this.browserVisibility === 'visible' && document.hasFocus() && this.sendPresence(), 20000) // dont bother delete this
64
65
  // slower send rate send when no focus
65
- setInterval(() => (this.browserVisibility !== 'visible' || document.hasFocus()) && this.sendPresence(), 60000) // dont bother delete this
66
+ sb.setInterval(() => (this.browserVisibility !== 'visible' || document.hasFocus()) && this.sendPresence(), 60000) // dont bother delete this
66
67
 
67
68
  onVisibilityChange((val) => {
68
69
  this.browserVisibility = val
@@ -73,8 +74,8 @@ export default class Store {
73
74
  this.device = this.getDeviceInfo()
74
75
 
75
76
  // try to get Google Analytics tracking id and client id by periodically checking it after an interval
76
- const _gaInterval = setInterval(() => {
77
- let user = this.kv.match('user') || {}
77
+ const _gaInterval = sb.setInterval(() => {
78
+ let user = this.cache.match('user') || {}
78
79
  if (!user.id) return // store not init
79
80
  var dev = this.getDeviceInfo()
80
81
  if (!dev.ga_tracking_ids || !dev.ga_client_id) return
@@ -142,7 +143,7 @@ export default class Store {
142
143
  await this.readyGate.entry()
143
144
  this.disconnect('account')
144
145
  await this.reconnect()
145
- setTimeout(this.pubsub.publish('resetCSS'), 10)
146
+ sb.setTimeout(this.pubsub.publish('resetCSS'), 10)
146
147
  }
147
148
 
148
149
  getDeviceInfo() {
@@ -225,7 +226,7 @@ export default class Store {
225
226
  // must ensure only call this function after init is done
226
227
  matchUser = () => {
227
228
  this._touchAcc()
228
- return this.kv.match('user')
229
+ return this.cache.match('user')
229
230
  }
230
231
 
231
232
  suggest_addresses = (keyword) => this.api.suggest_address(keyword)
@@ -293,7 +294,7 @@ export default class Store {
293
294
  listEvents = (id) => {
294
295
  if (!id || id === '*' || typeof id !== 'string') return
295
296
  if (!this.isInsync('events' + id)) {
296
- setTimeout(async () => {
297
+ sb.setTimeout(async () => {
297
298
  await this.readyGate.entry()
298
299
  await this.reconnectGate.entry(undefined, true)
299
300
  if (this.isInsync('events' + id)) return this.reconnectGate.open()
@@ -324,7 +325,16 @@ export default class Store {
324
325
  wsGate = new sb.Gate(true)
325
326
 
326
327
  // last widget screen
327
- matchLastview = () => this.kv.match('lastview') || {}
328
+ matchLastview = () => {
329
+ let lastView = this.kv.match('lastview') || {}
330
+
331
+ // make sure last view of correct user
332
+ let user = this.cache.match('user') || {}
333
+ if (!user.id) return {}
334
+ if (lastView.user_id != user.id) return {}
335
+ return lastView
336
+ }
337
+
328
338
  matchIsOpen = () => !!this.kv.match('isopen') // is widget currently open
329
339
  matchHasManuallyClosed = () => !!this.kv.match('hasManuallyClosed') // true if user has ever closed the widget
330
340
  matchClosePreviewAt = () => this.kv.match('close_preview_at') || 0
@@ -332,8 +342,8 @@ export default class Store {
332
342
  sendPresence = sb.throttle(
333
343
  async () => {
334
344
  await this.readyGate.entry()
335
- if (!sb.get(this.kv.match('user'), 'id')) return // store not init
336
- if (sb.isUserBanned(this.kv.match('user'))) return
345
+ if (!sb.get(this.cache.match('user'), 'id')) return // store not init
346
+ if (sb.isUserBanned(this.cache.match('user'))) return
337
347
 
338
348
  let hasfocus = this.browserVisibility === 'visible' && document.hasFocus()
339
349
  if (!hasfocus) {
@@ -454,10 +464,10 @@ export default class Store {
454
464
  // periodically send seen
455
465
  this.seenQueue = []
456
466
  clearInterval(this._seenInterval)
457
- this._seenInterval = setInterval(() => {
467
+ this._seenInterval = sb.setInterval(() => {
458
468
  // deduplicate
459
469
  this.seenQueue = [...new Set(this.seenQueue)]
460
- let user = this.kv.match('user') || {}
470
+ let user = this.cache.match('user') || {}
461
471
  sb.map(this.seenQueue, (id) => {
462
472
  var events = this.listEvents(id)
463
473
  if (!events) return
@@ -550,7 +560,7 @@ export default class Store {
550
560
 
551
561
  _setUser(user) {
552
562
  user = sb.cloneDeep(user)
553
- let olduser = this.kv.match('user') || {}
563
+ let olduser = this.cache.match('user') || {}
554
564
  var accid = olduser.account_id || user.account_id
555
565
  var id = olduser.id || user.id
556
566
 
@@ -567,7 +577,7 @@ export default class Store {
567
577
  olduser.account_id = accid
568
578
  olduser.id = id
569
579
 
570
- this.kv.put('user', olduser)
580
+ this.cache.put('user', olduser)
571
581
  this.pubsub.publish('account')
572
582
  }
573
583
 
@@ -666,7 +676,7 @@ export default class Store {
666
676
  if (!ev || !ev.type) return
667
677
  ev.created = sb.getMs(ev.created)
668
678
  if (ev.type === 'user_info_updated') {
669
- let user = sb.cloneDeep(this.kv.match('user'))
679
+ let user = sb.cloneDeep(this.cache.match('user'))
670
680
  let attrs = sb.get(ev, 'data.user.attributes') || []
671
681
  sb.map(attrs, (attr) => sb.setUserAttr(user, attr))
672
682
  this._setUser(user)
@@ -674,7 +684,7 @@ export default class Store {
674
684
  }
675
685
 
676
686
  // convo events
677
- let user = this.kv.match('user') || {}
687
+ let user = this.cache.match('user') || {}
678
688
  let cid = sb.convoOfEv(ev)
679
689
  let convo
680
690
 
@@ -702,7 +712,7 @@ export default class Store {
702
712
  // so re-get events of this conversation to ensure we dont miss any event
703
713
  if (ev.type === 'conversation_joined') {
704
714
  let members = sb.get(ev, 'data.conversation.members', [])
705
- let me = sb.find(members, (m) => m.id === this.kv.match('user').id)
715
+ let me = sb.find(members, (m) => m.id === this.cache.match('user').id)
706
716
  if (me) {
707
717
  await this.chain.reload(cid, (type, anchor, limit) => this.listmessageapi(type, anchor, limit))
708
718
  this.markSync('events' + cid)
@@ -733,7 +743,7 @@ export default class Store {
733
743
  }
734
744
 
735
745
  async restConvoEvent(ev) {
736
- let user = this.kv.match('user')
746
+ let user = this.cache.match('user')
737
747
  let cid = sb.convoOfEv(ev)
738
748
  let convo = this.cache.match('convo_' + cid) || {}
739
749
  if (ev.type === 'conversation_state_updated') {
@@ -858,7 +868,7 @@ export default class Store {
858
868
  await this.readyGate.entry()
859
869
  var idempotency = sb.randomString(36)
860
870
 
861
- let user = this.kv.match('user') || {}
871
+ let user = this.cache.match('user') || {}
862
872
 
863
873
  var event = {
864
874
  id: idempotency,
@@ -925,7 +935,7 @@ export default class Store {
925
935
  let count = 0
926
936
 
927
937
  // ignore invalid conversation
928
- let user = this.kv.match('user')
938
+ let user = this.cache.match('user')
929
939
 
930
940
  let channel = sb.get(convo, 'touchpoint.channel', '')
931
941
  if (channel && channel != 'subiz') return
@@ -964,7 +974,11 @@ export default class Store {
964
974
  }
965
975
  }
966
976
  closePreview = () => this.kv.put('close_preview_at', new sb.Date().getTime())
967
- setLastview = (view, opts) => this.kv.put('lastview', {view, opts})
977
+ setLastview = (view, opts) => {
978
+ let user = this.cache.match('user') || {}
979
+ if (!user.id) return // store not init
980
+ this.kv.put('lastview', {user_id: user.id, view, opts})
981
+ }
968
982
 
969
983
  matchLastPluginRun(pluginid) {
970
984
  let log = this.kv.match('plugin_run_logs') || {}
@@ -983,7 +997,7 @@ export default class Store {
983
997
  }
984
998
 
985
999
  sendImpression(id) {
986
- let user = this.kv.match('user') || {}
1000
+ let user = this.cache.match('user') || {}
987
1001
  let log = this.kv.match('plugin_run_logs') || {}
988
1002
  log[id] = {web_plugin_id: id, created: this.now()}
989
1003
  this.kv.put('plugin_run_logs', log)
@@ -998,7 +1012,7 @@ export default class Store {
998
1012
  }
999
1013
 
1000
1014
  sendConversion(id, fields, impressionToken) {
1001
- let user = this.kv.match('user') || {}
1015
+ let user = this.cache.match('user') || {}
1002
1016
  let submission = {account_id: user.account_id, user_id: user.id, fields: fields}
1003
1017
 
1004
1018
  let conv = this.kv.match('conversions') || {}
@@ -1034,7 +1048,7 @@ export default class Store {
1034
1048
  })
1035
1049
 
1036
1050
  // mark conversation as received
1037
- let user = this.kv.match('user') || {}
1051
+ let user = this.cache.match('user') || {}
1038
1052
  for (let i = 0; i < events.length; i++) {
1039
1053
  let ev = events[i].value
1040
1054
 
@@ -1055,15 +1069,15 @@ export default class Store {
1055
1069
  let startms = sb.Date.now()
1056
1070
 
1057
1071
  // store not init
1058
- if (!sb.get(this.kv.match('user'), 'id')) return setTimeout(() => this.loopTime(), 240000)
1072
+ if (!sb.get(this.cache.match('user'), 'id')) return sb.setTimeout(() => this.loopTime(), 240000)
1059
1073
 
1060
1074
  let {body: t, error} = await this.api.time()
1061
- if (error) return setTimeout(() => this.loopTime(), 30000)
1075
+ if (error) return sb.setTimeout(() => this.loopTime(), 30000)
1062
1076
  var latences = Math.abs(sb.Date.now() - startms) / 2
1063
1077
  var serverMs = new sb.Date(t).getTime() + latences
1064
1078
  var localMs = sb.Date.now()
1065
1079
  this.timeDiff = Math.floor(serverMs - localMs)
1066
- setTimeout(() => this.loopTime(), 240000)
1080
+ sb.setTimeout(() => this.loopTime(), 240000)
1067
1081
  }
1068
1082
 
1069
1083
  replaceFileUrl(src) {
@@ -1098,9 +1112,9 @@ export default class Store {
1098
1112
  if ((k || '').startsWith('__sb')) this.cookie.remove(k)
1099
1113
  })
1100
1114
  this.kv.destroy()
1101
- this.kv = new stor8.kv(new stor8.lsdb('sbz2020', this.inmem), 'kv')
1115
+ this.kv = new stor8.kv(new stor8.lsdb('sbz2023', this.inmem), 'kv')
1102
1116
  this.chain.destroy()
1103
- this.chain = new stor8.chain(new stor8.lsdb('cbz2020', true), 'ch')
1117
+ this.chain = new stor8.chain(new stor8.lsdb('cbz2023', true), 'ch')
1104
1118
  }
1105
1119
 
1106
1120
  destroy() {
@@ -1245,3 +1259,18 @@ let tabletCheck =
1245
1259
  /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(
1246
1260
  navigator.userAgent,
1247
1261
  )
1262
+
1263
+ let cleanLocalStorage = () => {
1264
+ try {
1265
+ localStorage
1266
+ } catch (e) {
1267
+ return
1268
+ }
1269
+ sb.setTimeout(() => {
1270
+ for (var key in localStorage) {
1271
+ if (key && (key.startsWith('cbz2020') || key.startsWith('sbz2020'))) {
1272
+ localStorage.removeItem(key)
1273
+ }
1274
+ }
1275
+ })
1276
+ }
@@ -14,8 +14,8 @@ export var stringify = f.contentWindow.JSON.stringify
14
14
  var parse = f.contentWindow.JSON.parse
15
15
  export var Date = f.contentWindow.Date
16
16
  export var requestAnimationFrame = f.contentWindow.requestAnimationFrame
17
- export var setTimeout = f.contentWindow.setTimeout
18
- export var setInterval = f.contentWindow.setInterval
17
+ export var setTimeout = f.contentWindow.setTimeout.bind(f.contentWindow)
18
+ export var setInterval = f.contentWindow.setInterval.bind(f.contentWindow)
19
19
 
20
20
  // convoOfEv extracts the ID of the conversation
21
21
  // that event is sent to