@subiz/widget-v4 4.1.202 → 4.1.204
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.md +1224 -0
- package/compiled_src/chatbox/ChatButton.js +19 -16
- package/compiled_src/chatbox/MessageInput.js +1 -0
- package/compiled_src/chatbox/main.js +28 -3
- package/compiled_src/lib.js +14 -0
- package/compiled_src/store/api.js +36 -4
- package/compiled_src/store/store.js +20 -4
- package/compiled_src/util/event.test.js +38 -0
- package/dist/19e1c4525c1.app.js +1 -0
- package/dist/{19d8a41ce33.chat.html → 19e1c4525c1.chat.html} +1 -1
- package/dist/19e1c4525c1.chat.js +1 -0
- package/dist/{19d8a41ce33.form.html → 19e1c4525c1.form.html} +1 -1
- package/dist/19e1c4525c1.form.js +1 -0
- package/dist/{19d8a41ce33.index.html → 19e1c4525c1.index.html} +1 -1
- package/dist/{19d8a41ce33.library.html → 19e1c4525c1.library.html} +1 -1
- package/dist/19e1c4525c1.library.js +1 -0
- package/dist/{19d8a41ce33.preview.html → 19e1c4525c1.preview.html} +1 -1
- package/dist/19e1c4525c1.preview.js +1 -0
- package/dist/19e1c4525c1.webview.js +1 -0
- package/dist/HASH +1 -1
- package/dist/screenshoot.js +104 -22
- package/package.json +8 -8
- package/src/chatbox/ChatButton.js +20 -15
- package/src/chatbox/MessageInput.js +1 -0
- package/src/chatbox/main.js +24 -4
- package/src/lib.js +14 -0
- package/src/store/api.js +41 -3
- package/src/store/store.js +28 -19
- package/src/util/event.test.js +31 -0
- package/dist/19d8a41ce33.app.js +0 -1
- package/dist/19d8a41ce33.chat.js +0 -1
- package/dist/19d8a41ce33.form.js +0 -1
- package/dist/19d8a41ce33.library.js +0 -1
- package/dist/19d8a41ce33.preview.js +0 -1
- package/dist/19d8a41ce33.webview.js +0 -1
- package/examples/track.js +0 -41
- /package/dist/{19d8a41ce33.127.js → 19e1c4525c1.127.js} +0 -0
- /package/dist/{19d8a41ce33.132.js → 19e1c4525c1.132.js} +0 -0
- /package/dist/{19d8a41ce33.185.js → 19e1c4525c1.185.js} +0 -0
- /package/dist/{19d8a41ce33.27.js → 19e1c4525c1.27.js} +0 -0
- /package/dist/{19d8a41ce33.278.js → 19e1c4525c1.278.js} +0 -0
- /package/dist/{19d8a41ce33.339.js → 19e1c4525c1.339.js} +0 -0
- /package/dist/{19d8a41ce33.459.js → 19e1c4525c1.459.js} +0 -0
- /package/dist/{19d8a41ce33.490.js → 19e1c4525c1.490.js} +0 -0
- /package/dist/{19d8a41ce33.74.js → 19e1c4525c1.74.js} +0 -0
- /package/dist/{19d8a41ce33.997.js → 19e1c4525c1.997.js} +0 -0
package/dist/HASH
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
19e1c4525c1
|
package/dist/screenshoot.js
CHANGED
|
@@ -1282,6 +1282,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
1282
1282
|
window.cancelAnimationFrame(this.animationframe);
|
|
1283
1283
|
}
|
|
1284
1284
|
});
|
|
1285
|
+
(Object.getOwnPropertyDescriptor(__WEBPACK_DEFAULT_EXPORT__, "name") || {}).writable || Object.defineProperty(__WEBPACK_DEFAULT_EXPORT__, "name", { value: "default", configurable: true });
|
|
1285
1286
|
function linearTransform(from, to, t, duration) {
|
|
1286
1287
|
if (eqFloat(from, to)) return from;
|
|
1287
1288
|
var s = to - from;
|
|
@@ -4389,12 +4390,31 @@ let trackResponseFn = (param, done) => {
|
|
|
4389
4390
|
_defineProperty(this, "time", _ => ajax.setBaseUrl(this.ApiURL).withCredentials(true).setParser('json').get('/time'));
|
|
4390
4391
|
_defineProperty(this, "updateUser", data => this.apireq.post(`/accounts/${this.accid}/users/${this.uid}`, data));
|
|
4391
4392
|
_defineProperty(this, "getUser", _ => this.apireq.get(`/accounts/${this.accid}/users/${this.uid}`));
|
|
4392
|
-
_defineProperty(this, "getAccountSetting", p => {
|
|
4393
|
+
_defineProperty(this, "getAccountSetting", async p => {
|
|
4393
4394
|
let href = util/* default */.A.get(document, 'location.href');
|
|
4395
|
+
let res = {};
|
|
4394
4396
|
if (p && p.bot_id) {
|
|
4395
|
-
|
|
4396
|
-
}
|
|
4397
|
-
|
|
4397
|
+
res = await this.apireq.addQuery('url', href).addQuery('bot_id', p.bot_id).get(`/accounts/${this.accid}/settings`);
|
|
4398
|
+
} else {
|
|
4399
|
+
res = await this.apireq.addQuery('url', href).get(`/accounts/${this.accid}/settings`);
|
|
4400
|
+
}
|
|
4401
|
+
if (res.error) return res;
|
|
4402
|
+
let plugins = util/* default */.A.get(res, 'body.plugins') || [];
|
|
4403
|
+
util/* default */.A.map(plugins, plugin => {
|
|
4404
|
+
if (plugin.type === 'popup') {
|
|
4405
|
+
let pages = util/* default */.A.get(plugin, 'popup.pages') || [];
|
|
4406
|
+
util/* default */.A.map(pages, page => {
|
|
4407
|
+
util/* default */.A.map(page.components, com => {
|
|
4408
|
+
if (com.type === 'image') {
|
|
4409
|
+
let url = util/* default */.A.get(com, 'image.url');
|
|
4410
|
+
util/* default */.A.set(com, 'image.url', fallbackGCSUrl(url));
|
|
4411
|
+
}
|
|
4412
|
+
});
|
|
4413
|
+
});
|
|
4414
|
+
}
|
|
4415
|
+
});
|
|
4416
|
+
util/* default */.A.set(res, 'body.plugins', plugins);
|
|
4417
|
+
return res;
|
|
4398
4418
|
});
|
|
4399
4419
|
_defineProperty(this, "sendImpression", impression => this.apireq.post(`/accounts/${this.accid}/campaigns/${impression.campaign_id}/impressions`, impression));
|
|
4400
4420
|
_defineProperty(this, "sendConversion", conversion => this.apireq.post(`/accounts/${this.accid}/campaigns/${conversion.campaign_id}/conversions`, conversion));
|
|
@@ -4580,6 +4600,20 @@ let trackResponseFn = (param, done) => {
|
|
|
4580
4600
|
});
|
|
4581
4601
|
}
|
|
4582
4602
|
});
|
|
4603
|
+
(Object.getOwnPropertyDescriptor(api, "name") || {}).writable || Object.defineProperty(api, "name", { value: "default", configurable: true });
|
|
4604
|
+
function fallbackGCSUrl(url) {
|
|
4605
|
+
try {
|
|
4606
|
+
const u = new URL(url);
|
|
4607
|
+
const isGCS = u.hostname === 'storage.googleapis.com';
|
|
4608
|
+
const isSubizBucket = u.pathname.startsWith('/public-gcs.subiz-cdn.com/');
|
|
4609
|
+
if (isGCS && isSubizBucket) {
|
|
4610
|
+
return `https://${u.pathname.slice(1)}`;
|
|
4611
|
+
}
|
|
4612
|
+
return url;
|
|
4613
|
+
} catch (e) {
|
|
4614
|
+
return url;
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4583
4617
|
;// ./src/store/lsdb.js
|
|
4584
4618
|
let memlocalStorage = __webpack_require__(450);
|
|
4585
4619
|
|
|
@@ -4641,6 +4675,7 @@ const LIMIT = 80;
|
|
|
4641
4675
|
});
|
|
4642
4676
|
}
|
|
4643
4677
|
});
|
|
4678
|
+
(Object.getOwnPropertyDescriptor(lsdb, "name") || {}).writable || Object.defineProperty(lsdb, "name", { value: "default", configurable: true });
|
|
4644
4679
|
function lsdb_toString(obj) {
|
|
4645
4680
|
if (obj === undefined) return 'null';
|
|
4646
4681
|
return JSON.stringify(obj);
|
|
@@ -4945,6 +4980,7 @@ let KvMaxSize = 500;
|
|
|
4945
4980
|
this.initialized = false;
|
|
4946
4981
|
}
|
|
4947
4982
|
});
|
|
4983
|
+
(Object.getOwnPropertyDescriptor(kv, "name") || {}).writable || Object.defineProperty(kv, "name", { value: "default", configurable: true });
|
|
4948
4984
|
;// ./src/store/api_fake.js
|
|
4949
4985
|
function api_fake_defineProperty(e, r, t) { return (r = api_fake_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4950
4986
|
function api_fake_toPropertyKey(t) { var i = api_fake_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
@@ -5035,6 +5071,7 @@ const OK200 = Promise.resolve({
|
|
|
5035
5071
|
};
|
|
5036
5072
|
}
|
|
5037
5073
|
});
|
|
5074
|
+
(Object.getOwnPropertyDescriptor(api_fake, "name") || {}).writable || Object.defineProperty(api_fake, "name", { value: "default", configurable: true });
|
|
5038
5075
|
function makeFakeConvo(accid, convoid, userid, agentid) {
|
|
5039
5076
|
let inteid = accid + '.subizv4.subikon';
|
|
5040
5077
|
return {
|
|
@@ -5333,6 +5370,7 @@ function makeFakeMessages(accid, convoid, userid, agentid) {
|
|
|
5333
5370
|
}
|
|
5334
5371
|
reconnect() {}
|
|
5335
5372
|
});
|
|
5373
|
+
(Object.getOwnPropertyDescriptor(realtime_fake, "name") || {}).writable || Object.defineProperty(realtime_fake, "name", { value: "default", configurable: true });
|
|
5336
5374
|
;// ./src/store/store.js
|
|
5337
5375
|
function store_defineProperty(e, r, t) { return (r = store_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5338
5376
|
function store_toPropertyKey(t) { var i = store_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
@@ -6853,21 +6891,8 @@ class ChatButton extends common/* Com */.Mw {
|
|
|
6853
6891
|
if (util/* default */.A.get(ev, 'type') !== 'message_sent') return;
|
|
6854
6892
|
let bytype = util/* default */.A.get(ev, 'by.type');
|
|
6855
6893
|
if (bytype !== 'system' && bytype !== 'agent' && bytype !== 'bot') return;
|
|
6856
|
-
let
|
|
6857
|
-
|
|
6858
|
-
if (!att) return;
|
|
6859
|
-
if (att.type === 'quick_replies') {
|
|
6860
|
-
isquickreplies = true;
|
|
6861
|
-
}
|
|
6862
|
-
});
|
|
6863
|
-
let format = util/* default */.A.get(ev, 'data.message.format');
|
|
6864
|
-
let block = util/* default */.A.get(ev, 'data.message.block');
|
|
6865
|
-
if (block || format == 'block') {
|
|
6866
|
-
if (util/* default */.A.isBlockEmpty(block) && isquickreplies) return;
|
|
6867
|
-
} else {
|
|
6868
|
-
let message = util/* default */.A.get(ev, 'data.message.text') || '';
|
|
6869
|
-
if (!message && isquickreplies) return;
|
|
6870
|
-
}
|
|
6894
|
+
let message = util/* default */.A.get(ev, 'data.message') || {};
|
|
6895
|
+
if (util/* default */.A.isEmptyMessage(message)) return;
|
|
6871
6896
|
let screen = util/* default */.A.get(this.props.store.matchLastview(), 'screen');
|
|
6872
6897
|
let minimized = util/* default */.A.get(this.props.store.matchLastview(), 'minimized');
|
|
6873
6898
|
if (screen === 'widget') return;
|
|
@@ -7226,6 +7251,9 @@ class ChatButton extends common/* Com */.Mw {
|
|
|
7226
7251
|
imgurl = this.props.store.replaceFileUrl(imgurl);
|
|
7227
7252
|
imgsrc = this.props.store.replaceFileUrl(imgsrc);
|
|
7228
7253
|
maskurl = this.props.store.replaceFileUrl(maskurl);
|
|
7254
|
+
imgurl = addVersionParam(imgurl);
|
|
7255
|
+
imgsrc = addVersionParam(imgsrc);
|
|
7256
|
+
maskurl = addVersionParam(maskurl);
|
|
7229
7257
|
if (!imgurl && !maskurl) {
|
|
7230
7258
|
whitebgcls += ' chat-button--white-bg--mask-only';
|
|
7231
7259
|
imgcontainerstyle = `
|
|
@@ -7357,6 +7385,19 @@ function randomAgent(agentM) {
|
|
|
7357
7385
|
const Ms30Mins = 30 * 60 * 1000;
|
|
7358
7386
|
const DEF_BG_URL = 'https://vcdn.subiz-cdn.com/file/bubble_11.svg?v=5';
|
|
7359
7387
|
const DEF_BG = 'linear-gradient(280.16deg, #0053d3 22.03%, #0265ff 78.2%)';
|
|
7388
|
+
function addVersionParam(url, version = 8) {
|
|
7389
|
+
if (!url) return url;
|
|
7390
|
+
try {
|
|
7391
|
+
const u = new URL(url);
|
|
7392
|
+
u.searchParams.set('v', version);
|
|
7393
|
+
return u.toString();
|
|
7394
|
+
} catch (e) {
|
|
7395
|
+
const [base, hash] = url.split('#');
|
|
7396
|
+
const hasQuery = base.includes('?');
|
|
7397
|
+
const newUrl = base + (hasQuery ? '&' : '?') + `v=${version}`;
|
|
7398
|
+
return hash ? newUrl + '#' + hash : newUrl;
|
|
7399
|
+
}
|
|
7400
|
+
}
|
|
7360
7401
|
;// ./src/chatbox/PoweredBy.js
|
|
7361
7402
|
var logo = __webpack_require__(9529);
|
|
7362
7403
|
|
|
@@ -7785,6 +7826,7 @@ class MessageInput extends common/* Com */.Mw {
|
|
|
7785
7826
|
}, 500);
|
|
7786
7827
|
this.resizeInput = util/* default */.A.throttle(function () {
|
|
7787
7828
|
const input = this.refMessageInput.current;
|
|
7829
|
+
if (!input) return;
|
|
7788
7830
|
input.style.setProperty('height', '1em', 'important');
|
|
7789
7831
|
const height = Math.min(200, input.scrollHeight);
|
|
7790
7832
|
input.style.setProperty('height', `${height}px`, 'important');
|
|
@@ -12159,6 +12201,9 @@ function encode(key) {
|
|
|
12159
12201
|
// EXTERNAL MODULE: ./src/chatbox/css.js
|
|
12160
12202
|
var chatbox_css = __webpack_require__(9278);
|
|
12161
12203
|
;// ./src/chatbox/main.js
|
|
12204
|
+
function main_defineProperty(e, r, t) { return (r = main_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
12205
|
+
function main_toPropertyKey(t) { var i = main_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
12206
|
+
function main_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
12162
12207
|
|
|
12163
12208
|
|
|
12164
12209
|
|
|
@@ -12168,6 +12213,10 @@ var chatbox_css = __webpack_require__(9278);
|
|
|
12168
12213
|
class Main extends common/* Com */.Mw {
|
|
12169
12214
|
constructor(props) {
|
|
12170
12215
|
super(props);
|
|
12216
|
+
main_defineProperty(this, "state", {
|
|
12217
|
+
cssReady: false,
|
|
12218
|
+
changing: false
|
|
12219
|
+
});
|
|
12171
12220
|
this.refButton = (0,preact_module/* createRef */._3)();
|
|
12172
12221
|
this.refWidget = (0,preact_module/* createRef */._3)();
|
|
12173
12222
|
}
|
|
@@ -12195,9 +12244,6 @@ class Main extends common/* Com */.Mw {
|
|
|
12195
12244
|
this.$cssStyleDiv.type = 'text/css';
|
|
12196
12245
|
this.$cssStyleDiv.id = 'subiz-style-for-' + this.props.plugin.id;
|
|
12197
12246
|
}
|
|
12198
|
-
this.setState({
|
|
12199
|
-
cssReady: false
|
|
12200
|
-
});
|
|
12201
12247
|
this.checkExpand();
|
|
12202
12248
|
this.props.store.onResetCSS(this, () => this.refreshCSS());
|
|
12203
12249
|
this.props.store.onConvoEvent(this, ev => this.onConvoEvent(ev));
|
|
@@ -12209,11 +12255,32 @@ class Main extends common/* Com */.Mw {
|
|
|
12209
12255
|
});
|
|
12210
12256
|
});
|
|
12211
12257
|
this.refreshCSS();
|
|
12258
|
+
let lastview = this.props.store.matchLastview() || {};
|
|
12259
|
+
let cid = util/* default */.A.get(lastview, 'opts.cid');
|
|
12260
|
+
if (cid) {
|
|
12261
|
+
this._last_cid = cid;
|
|
12262
|
+
this.setState({
|
|
12263
|
+
changing: true
|
|
12264
|
+
}, () => {
|
|
12265
|
+
this.props.store.fetchConvo(cid).then(() => {
|
|
12266
|
+
let convo = this.props.store.matchConvo(cid);
|
|
12267
|
+
if (cid != this._last_cid) return;
|
|
12268
|
+
this.setState({
|
|
12269
|
+
changing: false
|
|
12270
|
+
});
|
|
12271
|
+
if (!convo) return this.showWidget({});
|
|
12272
|
+
});
|
|
12273
|
+
});
|
|
12274
|
+
}
|
|
12212
12275
|
this.setState({
|
|
12213
12276
|
cssReady: true
|
|
12214
12277
|
});
|
|
12215
12278
|
}
|
|
12216
12279
|
render() {
|
|
12280
|
+
if (this.state.changing) {
|
|
12281
|
+
if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_changing_ready = util/* default */.A.Date.now();
|
|
12282
|
+
return null;
|
|
12283
|
+
}
|
|
12217
12284
|
if (!this.state.cssReady) {
|
|
12218
12285
|
if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_css_not_ready = util/* default */.A.Date.now();
|
|
12219
12286
|
return null;
|
|
@@ -12709,6 +12776,21 @@ class lib_Widget {
|
|
|
12709
12776
|
lib_defineProperty(this, "setViewingProduct", p => this.store.linkProduct(p));
|
|
12710
12777
|
lib_defineProperty(this, "getViewingProduct", () => this.store.getLinkedProduct());
|
|
12711
12778
|
lib_defineProperty(this, "track", v => this.store.track(v));
|
|
12779
|
+
lib_defineProperty(this, "event", async v => {
|
|
12780
|
+
await this.store.readyGate.entry();
|
|
12781
|
+
return this.store.api.sendEvent(v);
|
|
12782
|
+
});
|
|
12783
|
+
lib_defineProperty(this, "pageview", v => {
|
|
12784
|
+
v = v || {};
|
|
12785
|
+
return this.event({
|
|
12786
|
+
type: 'content_viewed',
|
|
12787
|
+
payload: {
|
|
12788
|
+
url: v.url || location.href,
|
|
12789
|
+
title: v.title || document.title,
|
|
12790
|
+
referrer: v.referrer || document.referrer
|
|
12791
|
+
}
|
|
12792
|
+
});
|
|
12793
|
+
});
|
|
12712
12794
|
this.impressionTokens = {};
|
|
12713
12795
|
this.domGate = new util/* default */.A.Gate();
|
|
12714
12796
|
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.
|
|
3
|
+
"version": "4.1.204",
|
|
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.
|
|
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.
|
|
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.
|
|
33
|
-
"puppeteer": "^
|
|
34
|
-
"webpack": "^5.
|
|
35
|
-
"webpack-bundle-analyzer": "^5.
|
|
32
|
+
"html-webpack-plugin": "^5.6.7",
|
|
33
|
+
"puppeteer": "^25.0.4",
|
|
34
|
+
"webpack": "^5.107.1",
|
|
35
|
+
"webpack-bundle-analyzer": "^5.3.0",
|
|
36
36
|
"webpack-cli": "^7.0.2",
|
|
37
|
-
"webpack-dev-server": "^5.2.
|
|
37
|
+
"webpack-dev-server": "^5.2.4"
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -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
|
|
31
|
-
|
|
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')
|
package/src/chatbox/main.js
CHANGED
|
@@ -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
|
@@ -317,6 +317,11 @@ class Widget {
|
|
|
317
317
|
getViewingProduct = () => this.store.getLinkedProduct()
|
|
318
318
|
|
|
319
319
|
track = (v) => this.store.track(v)
|
|
320
|
+
event = async (type, payload, options) => {
|
|
321
|
+
await this.store.readyGate.entry()
|
|
322
|
+
return this.store.api.sendEvent(normalizeCdpEvent(type, payload, options))
|
|
323
|
+
}
|
|
324
|
+
pageview = (v) => this.store.sendPageview(v)
|
|
320
325
|
|
|
321
326
|
async setLocale(locale) {
|
|
322
327
|
await this.domGate.entry()
|
|
@@ -398,6 +403,15 @@ class Widget {
|
|
|
398
403
|
}
|
|
399
404
|
}
|
|
400
405
|
|
|
406
|
+
function normalizeCdpEvent(type, payload, options) {
|
|
407
|
+
if (type && typeof type === 'object') return type
|
|
408
|
+
|
|
409
|
+
let data = {type: type}
|
|
410
|
+
if (payload !== undefined) data.payload = payload
|
|
411
|
+
if (options && typeof options === 'object') data = Object.assign({}, options, data)
|
|
412
|
+
return data
|
|
413
|
+
}
|
|
414
|
+
|
|
401
415
|
// for debugging purpose
|
|
402
416
|
window.__sbz_WIDGET = Widget
|
|
403
417
|
export default Widget
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/src/store/store.js
CHANGED
|
@@ -76,6 +76,13 @@ export default class Store {
|
|
|
76
76
|
this.sendPresence()
|
|
77
77
|
})
|
|
78
78
|
window.addEventListener('beforeunload', () => this.api.sendLostFocus())
|
|
79
|
+
this._lastPresenceURL = window.location.href
|
|
80
|
+
this._urlCheckInterval = sb.setInterval(() => {
|
|
81
|
+
if (this._die) return sb.clearInterval(this._urlCheckInterval)
|
|
82
|
+
if (this._lastPresenceURL === window.location.href) return
|
|
83
|
+
this._lastPresenceURL = window.location.href
|
|
84
|
+
this.sendPresence()
|
|
85
|
+
}, 2_000)
|
|
79
86
|
|
|
80
87
|
this.doNotStartBot = () => {
|
|
81
88
|
this._donotstartbot = true
|
|
@@ -508,24 +515,16 @@ export default class Store {
|
|
|
508
515
|
submitForm2 = (accid, token, data) => this.api.submitForm2(accid, token, data)
|
|
509
516
|
sendPresence = sb.throttle(
|
|
510
517
|
async () => {
|
|
518
|
+
if (!this._track_page_view) return
|
|
511
519
|
if (this._die) return dieErr
|
|
512
520
|
await this.readyGate.entry()
|
|
513
521
|
if (!sb.get(this.cache.match('user'), 'id')) return // store not init
|
|
514
522
|
if (sb.isUserBanned(this.cache.match('user'))) return
|
|
515
523
|
|
|
516
|
-
if (!this._track_page_view) return
|
|
517
|
-
|
|
518
524
|
let hasfocus = this.browserVisibility === 'visible' && document.hasFocus()
|
|
519
525
|
if (!hasfocus) return this.api.sendLostFocus()
|
|
520
526
|
|
|
521
|
-
this.
|
|
522
|
-
this.device,
|
|
523
|
-
location.href,
|
|
524
|
-
document.title,
|
|
525
|
-
this._currentViewingProduct.id,
|
|
526
|
-
this._currentViewingProduct.source_id,
|
|
527
|
-
this._currentViewingProduct.sku,
|
|
528
|
-
)
|
|
527
|
+
this.sendPageview()
|
|
529
528
|
},
|
|
530
529
|
1000, // dont send presence update too tight
|
|
531
530
|
{leading: false}, // dont send right after load. should send after content_view
|
|
@@ -915,21 +914,30 @@ export default class Store {
|
|
|
915
914
|
this.pubsub.publish('account')
|
|
916
915
|
}
|
|
917
916
|
|
|
917
|
+
async sendPageview(p) {
|
|
918
|
+
if (!p) p = {}
|
|
919
|
+
let device = Object.assign({}, this.device)
|
|
920
|
+
if (p.referrer) device.source_referrer = p.referrer
|
|
921
|
+
device.page_url = p.url || location.href
|
|
922
|
+
device.page_title = p.title || document.title
|
|
923
|
+
return this.api.sendContentView(
|
|
924
|
+
device,
|
|
925
|
+
p.url || location.href,
|
|
926
|
+
p.title || document.title,
|
|
927
|
+
this._currentViewingProduct.id,
|
|
928
|
+
this._currentViewingProduct.source_id,
|
|
929
|
+
this._currentViewingProduct.sku,
|
|
930
|
+
)
|
|
931
|
+
}
|
|
932
|
+
|
|
918
933
|
// send the content view, the first presence and record domain
|
|
919
934
|
async track(e) {
|
|
920
935
|
if (!e) {
|
|
921
|
-
let out = await this.
|
|
922
|
-
this.device,
|
|
923
|
-
location.href,
|
|
924
|
-
document.title,
|
|
925
|
-
this._currentViewingProduct.id,
|
|
926
|
-
this._currentViewingProduct.source_id,
|
|
927
|
-
this._currentViewingProduct.sku,
|
|
928
|
-
)
|
|
936
|
+
let out = await this.sendPageview()
|
|
929
937
|
|
|
930
938
|
let traffic_source = sb.get(out, 'body.by.device.source', '')
|
|
931
939
|
if (traffic_source) this.kv.put('traffic_source', traffic_source)
|
|
932
|
-
return
|
|
940
|
+
return out
|
|
933
941
|
}
|
|
934
942
|
|
|
935
943
|
if (typeof e === 'object') {
|
|
@@ -1501,6 +1509,7 @@ export default class Store {
|
|
|
1501
1509
|
this._die = true
|
|
1502
1510
|
this.clearBrowserData()
|
|
1503
1511
|
sb.clearInterval(this._seenInterval)
|
|
1512
|
+
sb.clearInterval(this._urlCheckInterval)
|
|
1504
1513
|
if (this.realtime) this.realtime.stop()
|
|
1505
1514
|
this.readyGate.close()
|
|
1506
1515
|
window.removeEventListener('blur', this.sendPresence)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var test = require('tape')
|
|
2
|
+
var {normalizeCdpEvent} = require('./event.js')
|
|
3
|
+
|
|
4
|
+
test('normalize cdp event new signature', (t) => {
|
|
5
|
+
t.deepEqual(
|
|
6
|
+
normalizeCdpEvent('content_viewed', {
|
|
7
|
+
url: 'https://example.com/products/pd2345',
|
|
8
|
+
title: 'Bàn phím cơ không dây',
|
|
9
|
+
}, {event_source_id: 'evt_1234'}),
|
|
10
|
+
{
|
|
11
|
+
type: 'content_viewed',
|
|
12
|
+
payload: {
|
|
13
|
+
url: 'https://example.com/products/pd2345',
|
|
14
|
+
title: 'Bàn phím cơ không dây',
|
|
15
|
+
},
|
|
16
|
+
event_source_id: 'evt_1234',
|
|
17
|
+
},
|
|
18
|
+
)
|
|
19
|
+
t.end()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('normalize cdp event without payload', (t) => {
|
|
23
|
+
t.deepEqual(normalizeCdpEvent('login'), {type: 'login'})
|
|
24
|
+
t.end()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('normalize cdp event keeps old object signature', (t) => {
|
|
28
|
+
let event = {type: 'product_viewed', payload: {id: 'pd2345'}}
|
|
29
|
+
t.equal(normalizeCdpEvent(event), event)
|
|
30
|
+
t.end()
|
|
31
|
+
})
|