@subiz/widget-v4 4.1.201 → 4.1.203

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 (45) hide show
  1. package/api.md +1284 -0
  2. package/compiled_src/bot.js +1 -7
  3. package/compiled_src/chatbox/ChatButton.js +19 -16
  4. package/compiled_src/chatbox/MessageInput.js +1 -0
  5. package/compiled_src/chatbox/Widget.js +1 -0
  6. package/compiled_src/chatbox/main.js +28 -3
  7. package/compiled_src/lib.js +16 -1
  8. package/compiled_src/store/api.js +36 -4
  9. package/compiled_src/store/store.js +14 -1
  10. package/compiled_src/util/common.js +18 -18
  11. package/dist/{19d6b530a9c.app.js → 19df158c2ea.app.js} +1 -1
  12. package/dist/{19d6b530a9c.chat.html → 19df158c2ea.chat.html} +1 -1
  13. package/dist/{19d6b530a9c.chat.js → 19df158c2ea.chat.js} +1 -1
  14. package/dist/{19d6b530a9c.form.html → 19df158c2ea.form.html} +1 -1
  15. package/dist/19df158c2ea.form.js +1 -0
  16. package/dist/{19d6b530a9c.index.html → 19df158c2ea.index.html} +1 -1
  17. package/dist/{19d6b530a9c.library.html → 19df158c2ea.library.html} +1 -1
  18. package/dist/{19d6b530a9c.library.js → 19df158c2ea.library.js} +1 -1
  19. package/dist/{19d6b530a9c.preview.html → 19df158c2ea.preview.html} +1 -1
  20. package/dist/{19d6b530a9c.preview.js → 19df158c2ea.preview.js} +1 -1
  21. package/dist/{19d6b530a9c.webview.js → 19df158c2ea.webview.js} +1 -1
  22. package/dist/HASH +1 -1
  23. package/dist/screenshoot.js +88 -39
  24. package/package.json +8 -8
  25. package/src/bot.js +1 -7
  26. package/src/chatbox/ChatButton.js +20 -15
  27. package/src/chatbox/MessageInput.js +1 -0
  28. package/src/chatbox/Widget.js +1 -1
  29. package/src/chatbox/main.js +24 -4
  30. package/src/lib.js +16 -1
  31. package/src/store/api.js +41 -3
  32. package/src/store/store.js +17 -2
  33. package/src/util/common.js +22 -21
  34. package/dist/19d6b530a9c.form.js +0 -1
  35. package/examples/track.js +0 -41
  36. /package/dist/{19d6b530a9c.127.js → 19df158c2ea.127.js} +0 -0
  37. /package/dist/{19d6b530a9c.132.js → 19df158c2ea.132.js} +0 -0
  38. /package/dist/{19d6b530a9c.185.js → 19df158c2ea.185.js} +0 -0
  39. /package/dist/{19d6b530a9c.27.js → 19df158c2ea.27.js} +0 -0
  40. /package/dist/{19d6b530a9c.278.js → 19df158c2ea.278.js} +0 -0
  41. /package/dist/{19d6b530a9c.339.js → 19df158c2ea.339.js} +0 -0
  42. /package/dist/{19d6b530a9c.459.js → 19df158c2ea.459.js} +0 -0
  43. /package/dist/{19d6b530a9c.490.js → 19df158c2ea.490.js} +0 -0
  44. /package/dist/{19d6b530a9c.74.js → 19df158c2ea.74.js} +0 -0
  45. /package/dist/{19d6b530a9c.997.js → 19df158c2ea.997.js} +0 -0
package/dist/HASH CHANGED
@@ -1 +1 @@
1
- 19d6b530a9c
1
+ 19df158c2ea
@@ -1971,12 +1971,6 @@ function filter(collection, predicate) {
1971
1971
  if (!collection) return [];
1972
1972
  if (!predicate) return collection;
1973
1973
  var out = [];
1974
- if (Array.isArray(collection)) {
1975
- for (let i = 0; i < collection.length; i++) {
1976
- if (predicate(collection[i], i)) out.push(collection[i]);
1977
- }
1978
- return out;
1979
- }
1980
1974
  if (typeof collection === 'object') {
1981
1975
  var keys = Object.keys(collection);
1982
1976
  for (let i = 0; i < keys.length; i++) {
@@ -1985,6 +1979,12 @@ function filter(collection, predicate) {
1985
1979
  }
1986
1980
  return out;
1987
1981
  }
1982
+ if (Array.isArray(collection)) {
1983
+ for (let i = 0; i < collection.length; i++) {
1984
+ if (predicate(collection[i], i)) out.push(collection[i]);
1985
+ }
1986
+ return out;
1987
+ }
1988
1988
  return out;
1989
1989
  }
1990
1990
  function includes(collection, value) {
@@ -1997,12 +1997,6 @@ function map(collection, predicate) {
1997
1997
  if (!collection) return [];
1998
1998
  if (!predicate) predicate = i => i;
1999
1999
  var out = [];
2000
- if (Array.isArray(collection)) {
2001
- for (let i = 0; i < collection.length; i++) {
2002
- out.push(predicate(collection[i], i));
2003
- }
2004
- return out;
2005
- }
2006
2000
  if (typeof collection === 'object') {
2007
2001
  var keys = Object.keys(collection);
2008
2002
  for (let i = 0; i < keys.length; i++) {
@@ -2011,6 +2005,12 @@ function map(collection, predicate) {
2011
2005
  }
2012
2006
  return out;
2013
2007
  }
2008
+ if (Array.isArray(collection)) {
2009
+ for (let i = 0; i < collection.length; i++) {
2010
+ out.push(predicate(collection[i], i));
2011
+ }
2012
+ return out;
2013
+ }
2014
2014
  return out;
2015
2015
  }
2016
2016
  function each(collection, predicate) {
@@ -2093,12 +2093,6 @@ function find(collection, f) {
2093
2093
  function findIndex(collection, f) {
2094
2094
  if (!collection) return -1;
2095
2095
  if (!f) return -1;
2096
- if (Array.isArray(collection)) {
2097
- for (let i = 0; i < collection.length; i++) {
2098
- if (f(collection[i], i)) return i;
2099
- }
2100
- return -1;
2101
- }
2102
2096
  if (typeof collection === 'object') {
2103
2097
  var keys = Object.keys(collection);
2104
2098
  for (let i = 0; i < keys.length; i++) {
@@ -2106,6 +2100,12 @@ function findIndex(collection, f) {
2106
2100
  if (f(collection[k], k)) return k;
2107
2101
  }
2108
2102
  }
2103
+ if (Array.isArray(collection)) {
2104
+ for (let i = 0; i < collection.length; i++) {
2105
+ if (f(collection[i], i)) return i;
2106
+ }
2107
+ return -1;
2108
+ }
2109
2109
  return -1;
2110
2110
  }
2111
2111
  function orderBy(a, k, d) {
@@ -4389,12 +4389,31 @@ let trackResponseFn = (param, done) => {
4389
4389
  _defineProperty(this, "time", _ => ajax.setBaseUrl(this.ApiURL).withCredentials(true).setParser('json').get('/time'));
4390
4390
  _defineProperty(this, "updateUser", data => this.apireq.post(`/accounts/${this.accid}/users/${this.uid}`, data));
4391
4391
  _defineProperty(this, "getUser", _ => this.apireq.get(`/accounts/${this.accid}/users/${this.uid}`));
4392
- _defineProperty(this, "getAccountSetting", p => {
4392
+ _defineProperty(this, "getAccountSetting", async p => {
4393
4393
  let href = util/* default */.A.get(document, 'location.href');
4394
+ let res = {};
4394
4395
  if (p && p.bot_id) {
4395
- return this.apireq.addQuery('url', href).addQuery('bot_id', p.bot_id).get(`/accounts/${this.accid}/settings`);
4396
- }
4397
- return this.apireq.addQuery('url', href).get(`/accounts/${this.accid}/settings`);
4396
+ res = await this.apireq.addQuery('url', href).addQuery('bot_id', p.bot_id).get(`/accounts/${this.accid}/settings`);
4397
+ } else {
4398
+ res = await this.apireq.addQuery('url', href).get(`/accounts/${this.accid}/settings`);
4399
+ }
4400
+ if (res.error) return res;
4401
+ let plugins = util/* default */.A.get(res, 'body.plugins') || [];
4402
+ util/* default */.A.map(plugins, plugin => {
4403
+ if (plugin.type === 'popup') {
4404
+ let pages = util/* default */.A.get(plugin, 'popup.pages') || [];
4405
+ util/* default */.A.map(pages, page => {
4406
+ util/* default */.A.map(page.components, com => {
4407
+ if (com.type === 'image') {
4408
+ let url = util/* default */.A.get(com, 'image.url');
4409
+ util/* default */.A.set(com, 'image.url', fallbackGCSUrl(url));
4410
+ }
4411
+ });
4412
+ });
4413
+ }
4414
+ });
4415
+ util/* default */.A.set(res, 'body.plugins', plugins);
4416
+ return res;
4398
4417
  });
4399
4418
  _defineProperty(this, "sendImpression", impression => this.apireq.post(`/accounts/${this.accid}/campaigns/${impression.campaign_id}/impressions`, impression));
4400
4419
  _defineProperty(this, "sendConversion", conversion => this.apireq.post(`/accounts/${this.accid}/campaigns/${conversion.campaign_id}/conversions`, conversion));
@@ -4580,6 +4599,19 @@ let trackResponseFn = (param, done) => {
4580
4599
  });
4581
4600
  }
4582
4601
  });
4602
+ function fallbackGCSUrl(url) {
4603
+ try {
4604
+ const u = new URL(url);
4605
+ const isGCS = u.hostname === 'storage.googleapis.com';
4606
+ const isSubizBucket = u.pathname.startsWith('/public-gcs.subiz-cdn.com/');
4607
+ if (isGCS && isSubizBucket) {
4608
+ return `https://${u.pathname.slice(1)}`;
4609
+ }
4610
+ return url;
4611
+ } catch (e) {
4612
+ return url;
4613
+ }
4614
+ }
4583
4615
  ;// ./src/store/lsdb.js
4584
4616
  let memlocalStorage = __webpack_require__(450);
4585
4617
 
@@ -5900,7 +5932,17 @@ class Store {
5900
5932
  }
5901
5933
  this.readyGate.close();
5902
5934
  accid = (accid || '').trim();
5903
- this.lightConvos = this.kv.match('light_convos') || {};
5935
+ let lightConvos = this.kv.match('light_convos') || {};
5936
+ this.lightConvos = {};
5937
+ util/* default */.A.map(lightConvos, convo => {
5938
+ let in7Day = convo.created > util/* default */.A.Date.now() - 7 * 24 * 3_600_000;
5939
+ let events = util/* default */.A.filter(convo.events, ev => ev.type === 'message_sent');
5940
+ let messages = util/* default */.A.map(events, ev => util/* default */.A.get(ev, 'data.message') || {});
5941
+ messages = util/* default */.A.filter(messages, msg => !util/* default */.A.isEmptyMessage(msg));
5942
+ if (in7Day && util/* default */.A.size(messages)) {
5943
+ this.lightConvos[convo.id] = convo;
5944
+ }
5945
+ });
5904
5946
  this.cache = new kv(new lsdb('sbz2023', true), 'kv');
5905
5947
  if (this.realtime) this.realtime.stop();
5906
5948
  if (this.fake) this.realtime = new realtime_fake();else this.realtime = new Realtime(this.RealtimeURL, realtimep, xhrsend, accid);
@@ -6124,6 +6166,9 @@ class Store {
6124
6166
  if (traffic_source) this.kv.put('traffic_source', traffic_source);
6125
6167
  return;
6126
6168
  }
6169
+ if (typeof e === 'object') {
6170
+ if (!e.data) e.data = {};
6171
+ }
6127
6172
  return this.api.sendEvent(e);
6128
6173
  }
6129
6174
  async onWs(ev) {
@@ -6840,21 +6885,8 @@ class ChatButton extends common/* Com */.Mw {
6840
6885
  if (util/* default */.A.get(ev, 'type') !== 'message_sent') return;
6841
6886
  let bytype = util/* default */.A.get(ev, 'by.type');
6842
6887
  if (bytype !== 'system' && bytype !== 'agent' && bytype !== 'bot') return;
6843
- let isquickreplies = false;
6844
- util/* default */.A.map(util/* default */.A.get(ev, 'data.message.attachments', []), att => {
6845
- if (!att) return;
6846
- if (att.type === 'quick_replies') {
6847
- isquickreplies = true;
6848
- }
6849
- });
6850
- let format = util/* default */.A.get(ev, 'data.message.format');
6851
- let block = util/* default */.A.get(ev, 'data.message.block');
6852
- if (block || format == 'block') {
6853
- if (util/* default */.A.isBlockEmpty(block) && isquickreplies) return;
6854
- } else {
6855
- let message = util/* default */.A.get(ev, 'data.message.text') || '';
6856
- if (!message && isquickreplies) return;
6857
- }
6888
+ let message = util/* default */.A.get(ev, 'data.message') || {};
6889
+ if (util/* default */.A.isEmptyMessage(message)) return;
6858
6890
  let screen = util/* default */.A.get(this.props.store.matchLastview(), 'screen');
6859
6891
  let minimized = util/* default */.A.get(this.props.store.matchLastview(), 'minimized');
6860
6892
  if (screen === 'widget') return;
@@ -7213,6 +7245,9 @@ class ChatButton extends common/* Com */.Mw {
7213
7245
  imgurl = this.props.store.replaceFileUrl(imgurl);
7214
7246
  imgsrc = this.props.store.replaceFileUrl(imgsrc);
7215
7247
  maskurl = this.props.store.replaceFileUrl(maskurl);
7248
+ imgurl = addVersionParam(imgurl);
7249
+ imgsrc = addVersionParam(imgsrc);
7250
+ maskurl = addVersionParam(maskurl);
7216
7251
  if (!imgurl && !maskurl) {
7217
7252
  whitebgcls += ' chat-button--white-bg--mask-only';
7218
7253
  imgcontainerstyle = `
@@ -7344,6 +7379,19 @@ function randomAgent(agentM) {
7344
7379
  const Ms30Mins = 30 * 60 * 1000;
7345
7380
  const DEF_BG_URL = 'https://vcdn.subiz-cdn.com/file/bubble_11.svg?v=5';
7346
7381
  const DEF_BG = 'linear-gradient(280.16deg, #0053d3 22.03%, #0265ff 78.2%)';
7382
+ function addVersionParam(url, version = 8) {
7383
+ if (!url) return url;
7384
+ try {
7385
+ const u = new URL(url);
7386
+ u.searchParams.set('v', version);
7387
+ return u.toString();
7388
+ } catch (e) {
7389
+ const [base, hash] = url.split('#');
7390
+ const hasQuery = base.includes('?');
7391
+ const newUrl = base + (hasQuery ? '&' : '?') + `v=${version}`;
7392
+ return hash ? newUrl + '#' + hash : newUrl;
7393
+ }
7394
+ }
7347
7395
  ;// ./src/chatbox/PoweredBy.js
7348
7396
  var logo = __webpack_require__(9529);
7349
7397
 
@@ -11724,6 +11772,7 @@ class Widget extends common/* Com */.Mw {
11724
11772
  agentids = agentids || util/* default */.A.agentsOfConvo(convo)[0];
11725
11773
  return (0,preact_module.h)("div", {
11726
11774
  class: "convo-list--item",
11775
+ "data-cid": convo.id,
11727
11776
  onClick: () => this.goToConvo(convo.id),
11728
11777
  key: convo.id
11729
11778
  }, (0,preact_module.h)(AgentsAvatar, {
@@ -12694,7 +12743,7 @@ class lib_Widget {
12694
12743
  lib_defineProperty(this, "getUser", () => util/* default */.A.parseJSON(util/* default */.A.stringify(this.store.matchUser())));
12695
12744
  lib_defineProperty(this, "setViewingProduct", p => this.store.linkProduct(p));
12696
12745
  lib_defineProperty(this, "getViewingProduct", () => this.store.getLinkedProduct());
12697
- lib_defineProperty(this, "track", () => this.store.track());
12746
+ lib_defineProperty(this, "track", v => this.store.track(v));
12698
12747
  this.impressionTokens = {};
12699
12748
  this.domGate = new util/* default */.A.Gate();
12700
12749
  this.store = new Store(ApiURL, FileURL, RealtimeURL, inmem, fake);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subiz/widget-v4",
3
- "version": "4.1.201",
3
+ "version": "4.1.203",
4
4
  "main": "./compiled_src/lib.js",
5
5
  "scripts": {
6
6
  "dev": "npx webpack serve --config webpack.dev.js",
@@ -11,7 +11,7 @@
11
11
  "dependencies": {
12
12
  "@subiz/ajax": "^3.0.22",
13
13
  "@subiz/flow": "^1.1.0",
14
- "@subiz/wsclient": "^4.0.34",
14
+ "@subiz/wsclient": "^4.0.35",
15
15
  "cookie_js": "1.4.2",
16
16
  "core-js": "^3.49.0",
17
17
  "css-loader": "5.2.7",
@@ -26,14 +26,14 @@
26
26
  "@babel/core": "^7.29.0",
27
27
  "@babel/plugin-proposal-class-properties": "^7.18.6",
28
28
  "@babel/plugin-transform-react-jsx": "^7.28.6",
29
- "@babel/preset-env": "^7.29.2",
29
+ "@babel/preset-env": "^7.29.5",
30
30
  "babel-loader": "^10.1.1",
31
31
  "babel-plugin-syntax-jsx": "^6.18.0",
32
- "html-webpack-plugin": "^5.6.6",
33
- "puppeteer": "^24.40.0",
34
- "webpack": "^5.105.4",
35
- "webpack-bundle-analyzer": "^5.2.0",
32
+ "html-webpack-plugin": "^5.6.7",
33
+ "puppeteer": "^24.43.1",
34
+ "webpack": "^5.106.2",
35
+ "webpack-bundle-analyzer": "^5.3.0",
36
36
  "webpack-cli": "^7.0.2",
37
- "webpack-dev-server": "^5.2.3"
37
+ "webpack-dev-server": "^5.2.4"
38
38
  }
39
39
  }
package/src/bot.js CHANGED
@@ -14,13 +14,7 @@ export default function (store) {
14
14
 
15
15
  let welcomMessages = bot.welcome_messages
16
16
  welcomMessages = sb.filter(welcomMessages, (msg) => {
17
- if (!sb.size(msg.attachments)) {
18
- if (msg.block || msg.format === 'block') {
19
- if (sb.isBlockEmpty(msg.block)) return false
20
- } else {
21
- if (!(msg.text || '').trim()) return false
22
- }
23
- }
17
+ if (sb.isEmptyMessage(msg)) return false
24
18
  return true
25
19
  })
26
20
  if (sb.size(welcomMessages)) {
@@ -27,21 +27,8 @@ export default class ChatButton extends Com {
27
27
  let bytype = sb.get(ev, 'by.type')
28
28
  if (bytype !== 'system' && bytype !== 'agent' && bytype !== 'bot') return
29
29
 
30
- let isquickreplies = false
31
- sb.map(sb.get(ev, 'data.message.attachments', []), (att) => {
32
- if (!att) return
33
- if (att.type === 'quick_replies') {
34
- isquickreplies = true
35
- }
36
- })
37
- let format = sb.get(ev, 'data.message.format')
38
- let block = sb.get(ev, 'data.message.block')
39
- if (block || format == 'block') {
40
- if (sb.isBlockEmpty(block) && isquickreplies) return
41
- } else {
42
- let message = sb.get(ev, 'data.message.text') || ''
43
- if (!message && isquickreplies) return
44
- }
30
+ let message = sb.get(ev, 'data.message') || {}
31
+ if (sb.isEmptyMessage(message)) return
45
32
  let screen = sb.get(this.props.store.matchLastview(), 'screen')
46
33
  let minimized = sb.get(this.props.store.matchLastview(), 'minimized')
47
34
  if (screen === 'widget') return
@@ -453,6 +440,9 @@ export default class ChatButton extends Com {
453
440
  imgurl = this.props.store.replaceFileUrl(imgurl)
454
441
  imgsrc = this.props.store.replaceFileUrl(imgsrc)
455
442
  maskurl = this.props.store.replaceFileUrl(maskurl)
443
+ imgurl = addVersionParam(imgurl)
444
+ imgsrc = addVersionParam(imgsrc)
445
+ maskurl = addVersionParam(maskurl)
456
446
 
457
447
  if (!imgurl && !maskurl) {
458
448
  whitebgcls += ' chat-button--white-bg--mask-only'
@@ -595,3 +585,18 @@ const Ms30Mins = 30 * 60 * 1000
595
585
  // v=5 trick to clear cache
596
586
  const DEF_BG_URL = 'https://vcdn.subiz-cdn.com/file/bubble_11.svg?v=5'
597
587
  const DEF_BG = 'linear-gradient(280.16deg, #0053d3 22.03%, #0265ff 78.2%)'
588
+
589
+ function addVersionParam(url, version = 8) {
590
+ if (!url) return url
591
+ try {
592
+ const u = new URL(url)
593
+ u.searchParams.set('v', version)
594
+ return u.toString()
595
+ } catch (e) {
596
+ // fallback nếu url không hợp lệ hoàn toàn
597
+ const [base, hash] = url.split('#')
598
+ const hasQuery = base.includes('?')
599
+ const newUrl = base + (hasQuery ? '&' : '?') + `v=${version}`
600
+ return hash ? newUrl + '#' + hash : newUrl
601
+ }
602
+ }
@@ -25,6 +25,7 @@ export default class MessageInput extends Com {
25
25
  this.resizeInput = sb.throttle(function () {
26
26
  // TODO: ctrl+A then press backspace dont reset size rightaway
27
27
  const input = this.refMessageInput.current
28
+ if (!input) return
28
29
  input.style.setProperty('height', '1em', 'important')
29
30
  const height = Math.min(200, input.scrollHeight)
30
31
  input.style.setProperty('height', `${height}px`, 'important')
@@ -739,7 +739,7 @@ export default class Widget extends Com {
739
739
  agentids = agentids || sb.agentsOfConvo(convo)[0]
740
740
 
741
741
  return (
742
- <div class='convo-list--item' onClick={() => this.goToConvo(convo.id)} key={convo.id}>
742
+ <div class='convo-list--item' data-cid={convo.id} onClick={() => this.goToConvo(convo.id)} key={convo.id}>
743
743
  <AgentsAvatar
744
744
  plugin={this.props.plugin}
745
745
  store={this.props.store}
@@ -17,6 +17,11 @@ export default class Main extends Com {
17
17
  this.refWidget = createRef()
18
18
  }
19
19
 
20
+ state = {
21
+ cssReady: false,
22
+ changing: false,
23
+ }
24
+
20
25
  refreshCSS() {
21
26
  // make sure you are still alive
22
27
  let plugins = this.props.store.matchPlugin()
@@ -45,10 +50,6 @@ export default class Main extends Com {
45
50
  this.$cssStyleDiv.id = 'subiz-style-for-' + this.props.plugin.id
46
51
  }
47
52
 
48
- this.setState({
49
- cssReady: false,
50
- })
51
-
52
53
  this.checkExpand()
53
54
  this.props.store.onResetCSS(this, () => this.refreshCSS())
54
55
  this.props.store.onConvoEvent(this, (ev) => this.onConvoEvent(ev))
@@ -60,10 +61,29 @@ export default class Main extends Com {
60
61
  })
61
62
  })
62
63
  this.refreshCSS()
64
+
65
+ let lastview = this.props.store.matchLastview() || {}
66
+ let cid = sb.get(lastview, 'opts.cid')
67
+ if (cid) {
68
+ this._last_cid = cid
69
+ this.setState({changing: true}, () => {
70
+ this.props.store.fetchConvo(cid).then(() => {
71
+ let convo = this.props.store.matchConvo(cid)
72
+ if (cid != this._last_cid) return // outdated
73
+ this.setState({changing: false})
74
+ if (!convo) return this.showWidget({}) // invalid convo, must redirect
75
+ })
76
+ })
77
+ }
78
+
63
79
  this.setState({cssReady: true})
64
80
  }
65
81
 
66
82
  render() {
83
+ if (this.state.changing) {
84
+ if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_changing_ready = sb.Date.now()
85
+ return null
86
+ }
67
87
  if (!this.state.cssReady) {
68
88
  if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_css_not_ready = sb.Date.now()
69
89
  return null
package/src/lib.js CHANGED
@@ -316,7 +316,22 @@ class Widget {
316
316
  setViewingProduct = (p) => this.store.linkProduct(p)
317
317
  getViewingProduct = () => this.store.getLinkedProduct()
318
318
 
319
- track = () => this.store.track()
319
+ track = (v) => this.store.track(v)
320
+ event = async (v) => {
321
+ await this.store.readyGate.entry()
322
+ return this.store.api.sendEvent(v)
323
+ }
324
+ pageview = (v) => {
325
+ v = v || {}
326
+ return this.event({
327
+ type: 'content_viewed',
328
+ payload: {
329
+ url: v.url || location.href,
330
+ title: v.title || document.title,
331
+ referrer: v.referrer || document.referrer,
332
+ },
333
+ })
334
+ }
320
335
 
321
336
  async setLocale(locale) {
322
337
  await this.domGate.entry()
package/src/store/api.js CHANGED
@@ -394,12 +394,33 @@ export default class {
394
394
  updateUser = (data) => this.apireq.post(`/accounts/${this.accid}/users/${this.uid}`, data)
395
395
 
396
396
  getUser = (_) => this.apireq.get(`/accounts/${this.accid}/users/${this.uid}`)
397
- getAccountSetting = (p) => {
397
+ getAccountSetting = async (p) => {
398
398
  let href = sb.get(document, 'location.href') // send full href, this could be used to select which bot (ai-agent) should be returned
399
+ let res = {}
399
400
  if (p && p.bot_id) {
400
- return this.apireq.addQuery('url', href).addQuery('bot_id', p.bot_id).get(`/accounts/${this.accid}/settings`)
401
+ res = await this.apireq.addQuery('url', href).addQuery('bot_id', p.bot_id).get(`/accounts/${this.accid}/settings`)
402
+ } else {
403
+ res = await this.apireq.addQuery('url', href).get(`/accounts/${this.accid}/settings`)
401
404
  }
402
- return this.apireq.addQuery('url', href).get(`/accounts/${this.accid}/settings`)
405
+ if (res.error) return res
406
+
407
+ // fix image error image url link in popup
408
+ let plugins = sb.get(res, 'body.plugins') || []
409
+ sb.map(plugins, (plugin) => {
410
+ if (plugin.type === 'popup') {
411
+ let pages = sb.get(plugin, 'popup.pages') || []
412
+ sb.map(pages, (page) => {
413
+ sb.map(page.components, (com) => {
414
+ if (com.type === 'image') {
415
+ let url = sb.get(com, 'image.url')
416
+ sb.set(com, 'image.url', fallbackGCSUrl(url))
417
+ }
418
+ })
419
+ })
420
+ }
421
+ })
422
+ sb.set(res, 'body.plugins', plugins)
423
+ return res
403
424
  }
404
425
 
405
426
  sendImpression = (impression) =>
@@ -432,3 +453,20 @@ export default class {
432
453
  suggest_address = (keyword) => this.apireq.setQuery({keyword: keyword}).get(`/accounts/${this.accid}/addresses`)
433
454
  create_ticket = (ticket) => this.apireq.post(`/accounts/${this.accid}/tickets`, ticket)
434
455
  }
456
+
457
+ function fallbackGCSUrl(url) {
458
+ try {
459
+ const u = new URL(url)
460
+
461
+ const isGCS = u.hostname === 'storage.googleapis.com'
462
+ const isSubizBucket = u.pathname.startsWith('/public-gcs.subiz-cdn.com/')
463
+
464
+ if (isGCS && isSubizBucket) {
465
+ return `https://${u.pathname.slice(1)}`
466
+ }
467
+
468
+ return url
469
+ } catch (e) {
470
+ return url
471
+ }
472
+ }
@@ -403,7 +403,7 @@ export default class Store {
403
403
 
404
404
  if (id === '*') {
405
405
  this._touchAcc()
406
- // combind with
406
+ // combind with light convo
407
407
  return sb.filter(this.cache.all(), (value, k) => k.startsWith('convo_')).concat(sb.map(this.lightConvos))
408
408
  }
409
409
 
@@ -633,7 +633,19 @@ export default class Store {
633
633
 
634
634
  this.readyGate.close()
635
635
  accid = (accid || '').trim()
636
- this.lightConvos = this.kv.match('light_convos') || {}
636
+ let lightConvos = this.kv.match('light_convos') || {}
637
+ this.lightConvos = {}
638
+ sb.map(lightConvos, (convo) => {
639
+ let in7Day = convo.created > sb.Date.now() - 7 * 24 * 3_600_000
640
+ let events = sb.filter(convo.events, (ev) => ev.type === 'message_sent')
641
+
642
+ let messages = sb.map(events, (ev) => sb.get(ev, 'data.message') || {})
643
+ messages = sb.filter(messages, (msg) => !sb.isEmptyMessage(msg))
644
+
645
+ if (in7Day && sb.size(messages)) {
646
+ this.lightConvos[convo.id] = convo
647
+ }
648
+ })
637
649
  this.cache = new KV(new LSDB('sbz2023', true), 'kv')
638
650
  if (this.realtime) this.realtime.stop()
639
651
  if (this.fake) this.realtime = new RealtimeFake()
@@ -920,6 +932,9 @@ export default class Store {
920
932
  return
921
933
  }
922
934
 
935
+ if (typeof e === 'object') {
936
+ if (!e.data) e.data = {}
937
+ }
923
938
  return this.api.sendEvent(e)
924
939
  }
925
940
 
@@ -329,13 +329,6 @@ export function filter(collection, predicate) {
329
329
  if (!predicate) return collection
330
330
 
331
331
  var out = []
332
- if (Array.isArray(collection)) {
333
- for (let i = 0; i < collection.length; i++) {
334
- if (predicate(collection[i], i)) out.push(collection[i])
335
- }
336
- return out
337
- }
338
-
339
332
  if (typeof collection === 'object') {
340
333
  var keys = Object.keys(collection)
341
334
  for (let i = 0; i < keys.length; i++) {
@@ -345,6 +338,13 @@ export function filter(collection, predicate) {
345
338
  return out
346
339
  }
347
340
 
341
+ if (Array.isArray(collection)) {
342
+ for (let i = 0; i < collection.length; i++) {
343
+ if (predicate(collection[i], i)) out.push(collection[i])
344
+ }
345
+ return out
346
+ }
347
+
348
348
  return out
349
349
  }
350
350
 
@@ -361,13 +361,6 @@ export function map(collection, predicate) {
361
361
  if (!predicate) predicate = (i) => i
362
362
 
363
363
  var out = []
364
- if (Array.isArray(collection)) {
365
- for (let i = 0; i < collection.length; i++) {
366
- out.push(predicate(collection[i], i))
367
- }
368
- return out
369
- }
370
-
371
364
  if (typeof collection === 'object') {
372
365
  var keys = Object.keys(collection)
373
366
  for (let i = 0; i < keys.length; i++) {
@@ -377,6 +370,13 @@ export function map(collection, predicate) {
377
370
  return out
378
371
  }
379
372
 
373
+ if (Array.isArray(collection)) {
374
+ for (let i = 0; i < collection.length; i++) {
375
+ out.push(predicate(collection[i], i))
376
+ }
377
+ return out
378
+ }
379
+
380
380
  return out
381
381
  }
382
382
 
@@ -483,13 +483,6 @@ function findIndex(collection, f) {
483
483
  if (!collection) return -1
484
484
  if (!f) return -1
485
485
 
486
- if (Array.isArray(collection)) {
487
- for (let i = 0; i < collection.length; i++) {
488
- if (f(collection[i], i)) return i
489
- }
490
- return -1
491
- }
492
-
493
486
  if (typeof collection === 'object') {
494
487
  var keys = Object.keys(collection)
495
488
  for (let i = 0; i < keys.length; i++) {
@@ -497,6 +490,14 @@ function findIndex(collection, f) {
497
490
  if (f(collection[k], k)) return k
498
491
  }
499
492
  }
493
+
494
+ if (Array.isArray(collection)) {
495
+ for (let i = 0; i < collection.length; i++) {
496
+ if (f(collection[i], i)) return i
497
+ }
498
+ return -1
499
+ }
500
+
500
501
  return -1
501
502
  }
502
503