@subiz/widget-v4 4.0.55 → 4.0.59

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 (54) hide show
  1. package/cloudflare_worker.js +1 -1
  2. package/compiled_src/chatbox/Header.js +2 -0
  3. package/compiled_src/lib.js +9 -2
  4. package/compiled_src/notif/notif.js +1 -1
  5. package/compiled_src/popup/popup.js +31 -1
  6. package/compiled_src/store/store.js +7 -5
  7. package/compiled_src/util/campaign.js +1 -1
  8. package/compiled_src/util/common.js +4 -2
  9. package/dist/{17d7ef84382.178.js → 178.js} +0 -0
  10. package/dist/{17d7ef81b7a.178.js → 17d939953e0.178.js} +0 -0
  11. package/dist/{17d7ef81b7a.213.js → 17d939953e0.213.js} +0 -0
  12. package/dist/{17d7ef81b7a.362.js → 17d939953e0.362.js} +0 -0
  13. package/dist/{17d7ef81b7a.441.js → 17d939953e0.441.js} +0 -0
  14. package/dist/17d939953e0.605.js +1 -0
  15. package/dist/{17d7ef81b7a.619.js → 17d939953e0.619.js} +0 -0
  16. package/dist/{17d7ef81b7a.678.js → 17d939953e0.678.js} +0 -0
  17. package/dist/17d939953e0.74.js +1 -0
  18. package/dist/{17d7ef81b7a.782.js → 17d939953e0.782.js} +0 -0
  19. package/dist/17d939953e0.app.js +1 -0
  20. package/dist/{17d7ef81b7a.index.html → 17d939953e0.index.html} +18 -2
  21. package/dist/{17d7ef81b7a.library.html → 17d939953e0.library.html} +18 -2
  22. package/dist/17d939953e0.library.js +1 -0
  23. package/dist/{17d7ef81b7a.preview.html → 17d939953e0.preview.html} +1 -1
  24. package/dist/17d939953e0.preview.js +1 -0
  25. package/dist/17d939953e0.screenshoot.js +1 -0
  26. package/dist/{17d7ef84382.213.js → 213.js} +0 -0
  27. package/dist/{17d7ef84382.362.js → 362.js} +0 -0
  28. package/dist/{17d7ef84382.441.js → 441.js} +0 -0
  29. package/dist/{17d7ef84382.605.js → 605.js} +1 -1
  30. package/dist/{17d7ef84382.619.js → 619.js} +0 -0
  31. package/dist/{17d7ef84382.678.js → 678.js} +0 -0
  32. package/dist/{17d7ef84382.74.js → 74.js} +2 -0
  33. package/dist/{17d7ef84382.782.js → 782.js} +0 -0
  34. package/dist/HASH +1 -1
  35. package/dist/screenshoot.html +1 -1
  36. package/dist/{17d7ef84382.screenshoot.js → screenshoot.js} +46 -9
  37. package/index.html +18 -2
  38. package/package.json +4 -4
  39. package/screenshoot.js +31 -0
  40. package/src/chatbox/Header.js +42 -34
  41. package/src/lib.js +8 -3
  42. package/src/notif/notif.js +1 -1
  43. package/src/plugin.js +11 -4
  44. package/src/popup/popup.js +25 -0
  45. package/src/store/store.js +9 -5
  46. package/src/util/campaign.js +2 -1
  47. package/src/util/common.js +4 -2
  48. package/webpack.screenshoot.js +0 -8
  49. package/dist/17d7ef81b7a.605.js +0 -1
  50. package/dist/17d7ef81b7a.74.js +0 -1
  51. package/dist/17d7ef81b7a.app.js +0 -1
  52. package/dist/17d7ef81b7a.library.js +0 -1
  53. package/dist/17d7ef81b7a.preview.js +0 -1
  54. package/dist/17d7ef81b7a.screenshoot.js +0 -1
@@ -2686,7 +2686,7 @@ function trackScrollingPercentage(percent, cb) {
2686
2686
  let scrollTop = e.srcElement.scrollingElement ? e.srcElement.scrollingElement.scrollTop : e.srcElement.scrollTop;
2687
2687
  let scrollHeight = e.srcElement.scrollingElement ? e.srcElement.scrollingElement.scrollHeight : e.srcElement.scrollHeight;
2688
2688
 
2689
- if (scrollTop > 0 && scrollHeight > 0 && scrollTop / scrollHeight >= percent) {
2689
+ if (scrollTop > 0 && scrollHeight > 0 && (scrollTop + window.innerHeight) / scrollHeight >= percent) {
2690
2690
  if (cb) cb();
2691
2691
  window.removeEventListener('scroll', handleScroll, false);
2692
2692
  }
@@ -3159,7 +3159,7 @@ var n,l,u,i,t,r,o,f,e={},c=[],s=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[c
3159
3159
  /******/ // This function allow to reference async chunks
3160
3160
  /******/ __webpack_require__.u = (chunkId) => {
3161
3161
  /******/ // return url for filenames based on template
3162
- /******/ return "17d7ef84382." + chunkId + ".js";
3162
+ /******/ return "" + chunkId + ".js";
3163
3163
  /******/ };
3164
3164
  /******/ })();
3165
3165
  /******/
@@ -4325,18 +4325,19 @@ class Store {
4325
4325
  if (!this.isInsync('account')) this.reconnect();
4326
4326
  }
4327
4327
 
4328
- async init(accid) {
4328
+ async init(accid, mask) {
4329
4329
  this.readyGate.close();
4330
4330
  accid = (accid || '').trim();
4331
4331
  this.api.setAuth({
4332
4332
  accid: accid
4333
4333
  });
4334
4334
  this.g_sync = {};
4335
- let mask = '';
4336
4335
 
4337
- try {
4338
- mask = this.cookie.get('__sbmask', '');
4339
- } catch (e) {}
4336
+ if (!mask) {
4337
+ try {
4338
+ mask = this.cookie.get('__sbmask', '');
4339
+ } catch (e) {}
4340
+ }
4340
4341
 
4341
4342
  let localstorageMask = this.kv.match('mask');
4342
4343
  if (!mask && localstorageMask) mask = localstorageMask;
@@ -4379,6 +4380,7 @@ class Store {
4379
4380
  await this.reconnect();
4380
4381
  this.readyGate.open();
4381
4382
  this.reconnectWs(accid, userId);
4383
+ return mask;
4382
4384
  }
4383
4385
 
4384
4386
  seenLoop() {
@@ -5551,8 +5553,13 @@ class Widget {
5551
5553
  xhttp.send();
5552
5554
  }
5553
5555
 
5554
- async setAccount(id, $container) {
5555
- await this.store.init(id);
5556
+ async waitReady(cb) {
5557
+ await this.store.readyGate.entry();
5558
+ cb();
5559
+ }
5560
+
5561
+ async setAccount(id, $container, mask, cb) {
5562
+ let outmask = await this.store.init(id, mask);
5556
5563
  if (!$container) $container = document.body;
5557
5564
  this.pluginMgr = new PluginMgr(this, $container);
5558
5565
  let clean = setInterval(() => {
@@ -5561,6 +5568,8 @@ class Widget {
5561
5568
  clearInterval(clean);
5562
5569
  }, 1000);
5563
5570
  this.domGate.open();
5571
+ cb && cb(outmask);
5572
+ return outmask;
5564
5573
  }
5565
5574
 
5566
5575
  _setAccount(id, $con) {
@@ -5705,6 +5714,34 @@ function main() {
5705
5714
  if (plugin.popup) plugin.popup.overlay = false;
5706
5715
  plugin._dont_close = true;
5707
5716
  plugin._page_index = 0;
5717
+ plugin.conditions = [];
5718
+
5719
+ if (plugin.type === 'notification') {
5720
+ if (!plugin.notification) return console.log('EMPTY PLUGIN');
5721
+
5722
+ if (!plugin.notification.profiles || plugin.notification.profiles.length == 0) {
5723
+ plugin.notification.profiles = [{
5724
+ address: 'Hàng Da, Hoàn Kiếm, Hà Nội',
5725
+ age: 26,
5726
+ avatar_url: 'https://vcdn.subiz-cdn.com/file/firegedmbhqftirxacho-avatar3.jpeg',
5727
+ country: 'VN',
5728
+ email: 'linhxx@gmail.com',
5729
+ gender: 'Female',
5730
+ fullname: 'Nguyễn Linh',
5731
+ phone: '0823588xxx'
5732
+ }, {
5733
+ address: 'Lũng Cú, Đồng Văn, Hà Giang',
5734
+ age: 23,
5735
+ avatar_url: 'https://vcdn.subiz-cdn.com/file/fiqvzdstytzxlbsguaci-ellipse_2319.png',
5736
+ country: 'VN',
5737
+ email: 'lannhoanggxx@gmail.com',
5738
+ gender: 'Female',
5739
+ name: 'Nguyễn Hoàng Lan',
5740
+ phone: '0326789xxx'
5741
+ }];
5742
+ }
5743
+ }
5744
+
5708
5745
  plugin.account_id = accid;
5709
5746
 
5710
5747
  widget._overridePlugin([plugin]);
package/index.html CHANGED
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
- <meta name="description" content="Subiz preview">
4
+ <meta name="description" content="Subiz preview" />
5
5
  <meta charset="utf-8" />
6
6
  <title>Widget v4</title>
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
@@ -32,7 +32,23 @@
32
32
  }
33
33
  window.subiz.q = []
34
34
  // set account it in the very first call
35
- window.subiz('setAccount', accid)
35
+ let mask = '' // old mask
36
+ window.subiz('setAccount', accid, undefined, mask, (mask) => {
37
+ console.log('MKA', mask)
38
+ })
39
+
40
+ subiz('overrideChatbox', {
41
+ type: 'chatbox',
42
+ chatbox: {
43
+ triggers: [{type: 'after_pageview'}],
44
+ hide_close_button: true,
45
+ desktop_button: {hidden: true},
46
+ mobile_button: {hidden: true},
47
+ },
48
+ })
49
+ subiz('waitReady', () => {})
50
+ subiz('shrinkWidget')
51
+ subiz('expandWidget')
36
52
  </script>
37
53
  </body>
38
54
  </html>
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@subiz/widget-v4",
3
- "version": "4.0.55",
3
+ "version": "4.0.59",
4
4
  "main": "./compiled_src/lib.js",
5
5
  "scripts": {
6
6
  "dev": "npx webpack serve --config webpack.dev.js",
7
- "build": "rm -rf dist && npx webpack --config webpack.prod.js && npx webpack --config webpack.screenshoot.js",
7
+ "build": "rm -rf dist && npx webpack --config webpack.screenshoot.js && npx webpack --config webpack.prod.js",
8
8
  "report": "npx webpack --config webpack.report.js",
9
9
  "lib": "rm -rf compiled_src && npx babel --out-dir=compiled_src src"
10
10
  },
@@ -15,7 +15,7 @@
15
15
  "@subiz/storage": "0.0.8",
16
16
  "@subiz/wsclient": "^3.1.7",
17
17
  "cookie_js": "1.4.2",
18
- "core-js": "^3.19.2",
18
+ "core-js": "^3.19.3",
19
19
  "css-loader": "^5.2.6",
20
20
  "file-loader": "^6.2.0",
21
21
  "less": "^4.1.2",
@@ -33,7 +33,7 @@
33
33
  "babel-plugin-syntax-jsx": "^6.18.0",
34
34
  "html-webpack-plugin": "^5.5.0",
35
35
  "puppeteer": "^12.0.1",
36
- "webpack": "^5.64.4",
36
+ "webpack": "^5.65.0",
37
37
  "webpack-bundle-analyzer": "^4.5.0",
38
38
  "webpack-cli": "^4.9.1",
39
39
  "webpack-dev-server": "^4.6.0"
package/screenshoot.js CHANGED
@@ -13,11 +13,42 @@ function main() {
13
13
  var $div = document.createElement('div')
14
14
  document.body.appendChild($div)
15
15
  let hash = document.location.hash.substr(1)
16
+
16
17
  let plugin = JSON.parse(decodeURIComponent(atob(hash)))
17
18
  plugin.triggers = [{type: 'after_pageview', after_pageview_sec: 0, enabled: true}]
18
19
  if (plugin.popup) plugin.popup.overlay = false
19
20
  plugin._dont_close = true
20
21
  plugin._page_index = 0
22
+ plugin.conditions = []
23
+
24
+ if (plugin.type === 'notification') {
25
+ if (!plugin.notification) return console.log('EMPTY PLUGIN')
26
+
27
+ if (!plugin.notification.profiles || plugin.notification.profiles.length == 0) {
28
+ plugin.notification.profiles = [
29
+ {
30
+ address: 'Hàng Da, Hoàn Kiếm, Hà Nội',
31
+ age: 26,
32
+ avatar_url: 'https://vcdn.subiz-cdn.com/file/firegedmbhqftirxacho-avatar3.jpeg',
33
+ country: 'VN',
34
+ email: 'linhxx@gmail.com',
35
+ gender: 'Female',
36
+ fullname: 'Nguyễn Linh',
37
+ phone: '0823588xxx',
38
+ },
39
+ {
40
+ address: 'Lũng Cú, Đồng Văn, Hà Giang',
41
+ age: 23,
42
+ avatar_url: 'https://vcdn.subiz-cdn.com/file/fiqvzdstytzxlbsguaci-ellipse_2319.png',
43
+ country: 'VN',
44
+ email: 'lannhoanggxx@gmail.com',
45
+ gender: 'Female',
46
+ name: 'Nguyễn Hoàng Lan',
47
+ phone: '0326789xxx',
48
+ },
49
+ ]
50
+ }
51
+ }
21
52
 
22
53
  plugin.account_id = accid
23
54
  widget._overridePlugin([plugin])
@@ -44,17 +44,19 @@ export default class Header extends Com {
44
44
  let state = acc.is_online ? this.props.t('agent_online') : this.props.t('agent_offline')
45
45
  let tagline = sb.get(accSetting, `tagline`, {})
46
46
  let desc = this.props.t.i18n(tagline) || accSetting.introduction || state
47
- let agentIdsJoined = sb.map(this.getAgentJoined(this.props.cid), agent => agent.id)
47
+ let agentIdsJoined = sb.map(this.getAgentJoined(this.props.cid), (agent) => agent.id)
48
48
  let cls = 'widget-header--inner widget-header--inner--collapsed'
49
49
  if (!show) cls += ' widget-header--inner--hidden'
50
50
 
51
51
  return (
52
52
  <div class={cls}>
53
53
  {this.renderBackButton()}
54
- <AgentsAvatar plugin={this.props.plugin} store={this.props.store} mode="secondary" agent_ids={agentIdsJoined} />
55
- <div class="widget-header--title-container">
56
- <div class="widget-header--title">{this.getTitle()}</div>
57
- <div class="widget-header--description" title={desc}>{desc}</div>
54
+ <AgentsAvatar plugin={this.props.plugin} store={this.props.store} mode='secondary' agent_ids={agentIdsJoined} />
55
+ <div class='widget-header--title-container'>
56
+ <div class='widget-header--title'>{this.getTitle()}</div>
57
+ <div class='widget-header--description' title={desc}>
58
+ {desc}
59
+ </div>
58
60
  </div>
59
61
  {this.renderCloseButton()}
60
62
  </div>
@@ -65,7 +67,7 @@ export default class Header extends Com {
65
67
  let accSetting = this.props.plugin.chatbox || {}
66
68
  let acc = this.props.store.matchAccount()
67
69
  let links = sb.get(accSetting, 'header.links') || []
68
- let $links = sb.map(links, link => {
70
+ let $links = sb.map(links, (link) => {
69
71
  if (!link.url || !link.type || link.type === 'subiz') return null
70
72
  if (link.type === 'email') {
71
73
  return (
@@ -79,7 +81,7 @@ export default class Header extends Com {
79
81
 
80
82
  return (
81
83
  <div>
82
- <a href={link.url} target="_blank" title={link.url} rel="noreferrer">
84
+ <a href={link.url} target='_blank' title={link.url} rel='noreferrer'>
83
85
  <i class={`social__links-logo social__links-logo--${link.type}`}></i>
84
86
  </a>
85
87
  </div>
@@ -90,7 +92,7 @@ export default class Header extends Com {
90
92
  Vui lòng hỏi chúng tôi bất cứ điều gì hoặc chia sẻ phản hồi của bạn`
91
93
  let tagline = sb.get(accSetting, `tagline`, {})
92
94
  var teamintro = this.props.t.i18n(tagline) || accSetting.introduction || this.props.t('team_intro') || DEFTEAMINTO
93
- var tags = sb.extractText(teamintro).map(tag => {
95
+ var tags = sb.extractText(teamintro).map((tag) => {
94
96
  if (tag.type === 'emoji') return <Emoji emojiCode={tag.text} />
95
97
  return tag.text
96
98
  })
@@ -99,17 +101,21 @@ Vui lòng hỏi chúng tôi bất cứ điều gì hoặc chia sẻ phản hồi
99
101
  if (!show) cls += ' widget-header--inner--hidden'
100
102
  return (
101
103
  <div class={cls}>
102
- <div class="widget-header-expand-container">
103
- <div class="widget-header--top-wrapper">
104
- <div class="widget-header--title">{this.getTitle()}</div>
104
+ <div class='widget-header-expand-container'>
105
+ <div class='widget-header--top-wrapper'>
106
+ <div class='widget-header--title'>{this.getTitle()}</div>
105
107
  {this.renderCloseButton()}
106
108
  </div>
107
- <div class="widget_header__body widget_header__body__social">
108
- <img alt="logo" class="social__account_logo" src={this.props.store.replaceFileUrl(sb.get(acc, 'logo_url'))} />
109
+ <div class='widget_header__body widget_header__body__social'>
110
+ <img
111
+ alt='logo'
112
+ class='social__account_logo'
113
+ src={this.props.store.replaceFileUrl(sb.get(acc, 'logo_url'))}
114
+ />
109
115
 
110
116
  <div>
111
- <div class="social__introduction">{tags}</div>
112
- <div class="social__links">{$links}</div>
117
+ <div class='social__introduction'>{tags}</div>
118
+ <div class='social__links'>{$links}</div>
113
119
  </div>
114
120
  </div>
115
121
  </div>
@@ -123,7 +129,7 @@ Vui lòng hỏi chúng tôi bất cứ điều gì hoặc chia sẻ phản hồi
123
129
  Vui lòng hỏi chúng tôi bất cứ điều gì hoặc chia sẻ phản hồi của bạn`
124
130
  let tagline = sb.get(accSetting, `tagline`, {})
125
131
  var teamintro = this.props.t.i18n(tagline) || accSetting.introduction || this.props.t('team_intro') || DEFTEAMINTO
126
- var tags = sb.extractText(teamintro).map(tag => {
132
+ var tags = sb.extractText(teamintro).map((tag) => {
127
133
  if (tag.type === 'emoji') return <Emoji emojiCode={tag.text} />
128
134
  return tag.text
129
135
  })
@@ -132,17 +138,17 @@ Vui lòng hỏi chúng tôi bất cứ điều gì hoặc chia sẻ phản hồi
132
138
  if (!show) cls += ' widget-header--inner--hidden'
133
139
  return (
134
140
  <div class={cls}>
135
- <div class="widget-header-expand-container">
136
- <div class="widget-header--top-wrapper">
137
- <div class="widget-header--title">{this.getTitle()}</div>
141
+ <div class='widget-header-expand-container'>
142
+ <div class='widget-header--top-wrapper'>
143
+ <div class='widget-header--title'>{this.getTitle()}</div>
138
144
  {this.renderCloseButton()}
139
145
  </div>
140
- <div class="widget_header__body">
141
- <div class="widget-header--avatar-wrapper">
142
- <AgentsAvatar plugin={this.props.plugin} store={this.props.store} mode="primary" />
146
+ <div class='widget_header__body'>
147
+ <div class='widget-header--avatar-wrapper'>
148
+ <AgentsAvatar plugin={this.props.plugin} store={this.props.store} mode='primary' />
143
149
  </div>
144
- <div class="widget-header--title-container">
145
- <div class="widget-header--description">{tags}</div>
150
+ <div class='widget-header--title-container'>
151
+ <div class='widget-header--description'>{tags}</div>
146
152
  </div>
147
153
  </div>
148
154
  </div>
@@ -170,32 +176,34 @@ Vui lòng hỏi chúng tôi bất cứ điều gì hoặc chia sẻ phản hồi
170
176
  let user = this.props.store.matchUser()
171
177
 
172
178
  let unreadcount = 0
173
- sb.map(allconvos, convo => {
179
+ sb.map(allconvos, (convo) => {
174
180
  if (convo.id == this.props.cid) return
175
181
  if (!sb.isConvoSeen(convo, user.id)) unreadcount++
176
182
  })
177
183
 
178
184
  if (unreadcount !== 0) {
179
- $unreadcount = <span class="widget-header--total-unread-convo">{unreadcount}</span>
185
+ $unreadcount = <span class='widget-header--total-unread-convo'>{unreadcount}</span>
180
186
  }
181
187
  return (
182
188
  <div
183
189
  class={`widget-header--wrap-button-back ${unreadcount ? 'widget-header--has-convo-unred' : ''}`}
184
- onClick={e => this.onBackClick(e)}>
185
- <div class="widget-header--button-back" data-tooltip={this.props.t('menu_back')}></div>
190
+ onClick={(e) => this.onBackClick(e)}>
191
+ <div class='widget-header--button-back' data-tooltip={this.props.t('menu_back')}></div>
186
192
  {$unreadcount}
187
193
  </div>
188
194
  )
189
195
  }
190
196
 
191
197
  renderCloseButton() {
198
+ let accSetting = this.props.plugin.chatbox || {}
199
+ if (accSetting.hide_close_button) return null
192
200
  return (
193
201
  <div
194
- class="widget-header--button widget-header--button-close"
202
+ class='widget-header--button widget-header--button-close'
195
203
  data-tooltip={this.props.t('close')}
196
- data-tooltip-position="bottom"
197
- onClick={e => this.onCloseClick(e)}>
198
- <span class="widget-header--button-close-icon"></span>
204
+ data-tooltip-position='bottom'
205
+ onClick={(e) => this.onCloseClick(e)}>
206
+ <span class='widget-header--button-close-icon'></span>
199
207
  </div>
200
208
  )
201
209
  }
@@ -214,9 +222,9 @@ Vui lòng hỏi chúng tôi bất cứ điều gì hoặc chia sẻ phản hồi
214
222
 
215
223
  getAgentJoined(cid) {
216
224
  var convo = this.props.store.matchConvo(cid) || {}
217
- let joined = sb.filter(convo.members, mem => mem.type === 'agent' && mem.membership === 'active')
225
+ let joined = sb.filter(convo.members, (mem) => mem.type === 'agent' && mem.membership === 'active')
218
226
  return joined
219
227
  }
220
228
  }
221
229
 
222
- let getJoinedNameMember = agents => sb.map(agents, agent => agent.name).join(', ')
230
+ let getJoinedNameMember = (agents) => sb.map(agents, (agent) => agent.name).join(', ')
package/src/lib.js CHANGED
@@ -32,9 +32,13 @@ class Widget {
32
32
  xhttp.send()
33
33
  }
34
34
 
35
- async setAccount(id, $container) {
36
- await this.store.init(id)
35
+ async waitReady(cb) {
36
+ await this.store.readyGate.entry()
37
+ cb()
38
+ }
37
39
 
40
+ async setAccount(id, $container, mask, cb) {
41
+ let outmask = await this.store.init(id, mask)
38
42
  // add container to client site
39
43
  if (!$container) $container = document.body
40
44
  this.pluginMgr = new PluginMgr(this, $container)
@@ -45,8 +49,9 @@ class Widget {
45
49
  this.pluginMgr.destroy()
46
50
  clearInterval(clean)
47
51
  }, 1000)
48
-
49
52
  this.domGate.open()
53
+ cb && cb(outmask)
54
+ return outmask
50
55
  }
51
56
 
52
57
  // deprecated
@@ -100,7 +100,7 @@ export default class Notif extends Com {
100
100
  this.setState({closeAnimation: false})
101
101
  let timestamp = this.randomTimestampt()
102
102
  let profiles = sb.get(this.props, 'plugin.notification.profiles', [])
103
- let user = profiles[Math.floor(Math.random() * sb.size(profiles))]
103
+ let user = profiles[Math.floor(Math.random() * sb.size(profiles))] || {}
104
104
  // make sure image loaded
105
105
  if (user.avatar_url && user.avatar_url.startsWith('http')) {
106
106
  await sb.preloadImg(user.avatar_url)
package/src/plugin.js CHANGED
@@ -29,10 +29,9 @@ function Plugin(plugin, store, $container, lib) {
29
29
 
30
30
  this.getState = () => state
31
31
 
32
- var run = async function () {
32
+ var run = async function() {
33
33
  if (_destroy) return
34
34
  if (state !== 'hold') return
35
-
36
35
  // dont run converted plugin twice
37
36
  if (plugin.type === 'popup' && store.isConverted(plugin.id)) return
38
37
 
@@ -375,8 +374,16 @@ const getLocale = (plugin, loc) => {
375
374
  if (found) return found
376
375
 
377
376
  found = sb.find(plugin.locales, (l) => {
378
- l = l.replace('-', '_').split('_')[0].trim().toLowerCase()
379
- let compareloc = loc.replace('-', '_').split('_')[0].trim().toLowerCase()
377
+ l = l
378
+ .replace('-', '_')
379
+ .split('_')[0]
380
+ .trim()
381
+ .toLowerCase()
382
+ let compareloc = loc
383
+ .replace('-', '_')
384
+ .split('_')[0]
385
+ .trim()
386
+ .toLowerCase()
380
387
  return l == compareloc
381
388
  })
382
389
  if (found) return found
@@ -13,6 +13,7 @@ export default class Popup extends Com {
13
13
  closeAnimation: true,
14
14
  pressedSubmit: false,
15
15
  imageReady: false,
16
+ fontReady: false,
16
17
  }
17
18
 
18
19
  constructor(props) {
@@ -39,14 +40,37 @@ export default class Popup extends Com {
39
40
  }
40
41
  })
41
42
  })
43
+ delete fonts.undefined
44
+ delete fonts.null
45
+ delete fonts['']
42
46
 
43
47
  if (sb.size(images) == 0) this.setState({imageReady: true})
44
48
  // preload images and fonts
45
49
  sb.map(images, (_, image) => sb.preloadImg(image, () => this.setState({imageReady: true})))
46
50
  sb.preloadWebfonts(Object.keys(fonts))
51
+ setTimeout(async () => {
52
+ await this.waitForFont(Object.keys(fonts))
53
+ this.setState({fontReady: true})
54
+ })
47
55
  })
48
56
  }
49
57
 
58
+ async waitForFont(fonts) {
59
+ if (sb.size(fonts) == 0) return
60
+ // 2 sec timeout
61
+ let ready = {}
62
+ for (var t = 0; t < 10; t++) {
63
+ for (var i = 0; i < fonts.length; i++) {
64
+ try {
65
+ if (document.fonts.check('normal 16px ' + fonts[i])) ready[fonts[i]] = true
66
+ if (Object.keys(readycount) == fonts.length) return
67
+ } catch (e) {}
68
+ }
69
+ await sb.sleep(200)
70
+ }
71
+ return
72
+ }
73
+
50
74
  openPopup() {
51
75
  this.setState({close: false})
52
76
  }
@@ -833,6 +857,7 @@ export default class Popup extends Com {
833
857
  if (!this.props.t) return null
834
858
  if (!this.state.cssready) return null
835
859
  if (!this.state.imageReady) return null
860
+ if (!this.state.fontReady) return null
836
861
  if (this.state.close) return null
837
862
 
838
863
  let popup = sb.get(this.props.plugin, 'popup', {})
@@ -276,16 +276,18 @@ export default class Store {
276
276
 
277
277
  now = () => sb.Date.now() + this.timeDiff // millisecond on server
278
278
 
279
- async init(accid) {
279
+ async init(accid, mask) {
280
280
  this.readyGate.close()
281
281
  accid = (accid || '').trim()
282
282
  this.api.setAuth({accid: accid})
283
283
 
284
284
  this.g_sync = {}
285
- let mask = '' // try to find mask in cookie
286
- try {
287
- mask = this.cookie.get('__sbmask', '')
288
- } catch (e) {}
285
+ // try to find mask in cookie
286
+ if (!mask) {
287
+ try {
288
+ mask = this.cookie.get('__sbmask', '')
289
+ } catch (e) {}
290
+ }
289
291
 
290
292
  let localstorageMask = this.kv.match('mask')
291
293
  // cookie is deleted, fallback to local storage
@@ -333,6 +335,8 @@ export default class Store {
333
335
  await this.reconnect()
334
336
  this.readyGate.open()
335
337
  this.reconnectWs(accid, userId)
338
+
339
+ return mask
336
340
  }
337
341
 
338
342
  seenQueue = [] // convoid will be seen
@@ -14,11 +14,12 @@ export function trackExitIntent(cb) {
14
14
  export function trackScrollingPercentage(percent, cb) {
15
15
  let handleScroll = (e) => {
16
16
  let scrollTop = e.srcElement.scrollingElement ? e.srcElement.scrollingElement.scrollTop : e.srcElement.scrollTop
17
+
17
18
  let scrollHeight = e.srcElement.scrollingElement
18
19
  ? e.srcElement.scrollingElement.scrollHeight
19
20
  : e.srcElement.scrollHeight
20
21
 
21
- if (scrollTop > 0 && scrollHeight > 0 && scrollTop / scrollHeight >= percent) {
22
+ if (scrollTop > 0 && scrollHeight > 0 && (scrollTop + window.innerHeight) / scrollHeight >= percent) {
22
23
  if (cb) cb()
23
24
  window.removeEventListener('scroll', handleScroll, false)
24
25
  }
@@ -905,7 +905,7 @@ export function getDayName(dayOfWeek) {
905
905
  }
906
906
 
907
907
  let loadedFonts = {}
908
- export function preloadWebfonts(fonts) {
908
+ export function preloadWebfonts(fonts, done) {
909
909
  for (var i = 0; i < fonts.length; i++) {
910
910
  let font = fonts[i]
911
911
  if (!font) continue
@@ -920,7 +920,9 @@ export function preloadWebfonts(fonts) {
920
920
  // Visible - so we can measure it - but not on the screen
921
921
  node.style.position = 'absolute'
922
922
  node.style.display = 'block'
923
- node.style.fontSize = '1px'
923
+ node.style.opacity = '0.1'
924
+ node.style.color = 'transparent'
925
+ node.style.fontSize = '20px'
924
926
  node.style.height = '0px'
925
927
  node.style.width = '0px'
926
928
 
@@ -6,14 +6,6 @@ webpackconfig.output.publicPath = './'
6
6
 
7
7
  webpackconfig.entry = {screenshoot: './screenshoot.js'}
8
8
 
9
- const HASH = Date.now().toString(16)
10
- // create hash
11
- if (!fs.existsSync('dist')) fs.mkdirSync('dist')
12
- fs.writeFileSync('dist/HASH', HASH)
13
-
14
- webpackconfig.output.chunkFilename = HASH + '.[name].js'
15
- webpackconfig.output.filename = HASH + '.[name].js'
16
-
17
9
  webpackconfig.optimization.minimize = false
18
10
  webpackconfig.mode = 'production'
19
11
  webpackconfig.plugins = [
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunk_subiz_widget_v4=self.webpackChunk_subiz_widget_v4||[]).push([[605],{2493:(t,e,s)=>{s.d(e,{M:()=>o,u:()=>n});var i=s(6400);s(819);class o extends i.wA{constructor(t){super(t),this._isMounted=!0,setTimeout((()=>{if(this.componentWillUnmount){let t=this.componentWillUnmount.bind(this);this.componentWillUnmount=()=>{t(),this._isMounted=!1}}}),10)}}class n extends o{constructor(t){super(t),this.setWrapperRef=this.setWrapperRef.bind(this),this.onClick=this.onClick.bind(this)}componentDidMount(){document.addEventListener("mousedown",this.onClick)}componentWillUnmount(){document.removeEventListener("mousedown",this.onClick)}setWrapperRef(t){this.wrapperRef=t}onClick(t){this.wrapperRef&&!this.wrapperRef.contains(t.target)&&this.props.onClickaway&&this.props.onClickaway()}render(){return(0,i.h)("div",{ref:this.setWrapperRef},this.props.children)}}},9605:(t,e,s)=>{s.r(e),s.d(e,{default:()=>r});var i=s(819),o=s(6400),n=s(2493);let a=s.e(362).then(s.bind(s,362));class r extends n.M{constructor(t){var e,s;super(t),s={close:!0,cssready:!1,closeAnimation:!0,imageReady:!1,user:{},timestamp:"",message:"",title:"",last_show:0},(e="state")in this?Object.defineProperty(this,e,{value:s,enumerable:!0,configurable:!0,writable:!0}):this[e]=s,setTimeout((async()=>{let{body:t}=await this.props.store.sendImpression(this.props.plugin.id);this.impressionToken=i.Z.get(t,"impression_token")||"";let e=i.Z.get(this.props,"plugin.notification.background_url");i.Z.preloadImg(e,(()=>this.setState({imageReady:!0})))}))}setOver(t){this.mouse_leave=t?0:i.Z.Date.now()}randomTimestampt(){let t=Math.floor(5*Math.random());return 0==t?this.props.t("just_now"):1==t?"1 "+this.props.t("minute_ago"):2==t?"2 "+this.props.t("minutes_ago"):3==t?"3 "+this.props.t("minutes_ago"):"4 "+this.props.t("minutes_ago")}onClick(t){if(t.stopPropagation(),this.props.plugin._dont_follow)return;this.props.store.sendConversion(this.props.plugin.id,null,this.impressionToken);let e=i.Z.get(this.props,"plugin.notification.url");return e?(e.startsWith("http://")||e.startsWith("https://")||(e="//"+e),i.Z.get(this.props,"plugin.notification.new_tab",!1)?window.open(e):void(window.location.href=e)):void 0}onCloseButtonClick(t){t.preventDefault(),t.stopPropagation(),this.setClose(!0)}renderCloseButton(){return(0,o.h)("div",{class:"btn_close",onClick:t=>this.onCloseButtonClick(t)},(0,o.h)("svg",{class:"btn_close__icon",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24","stroke-linecap":"round","stroke-linejoin":"round"},(0,o.h)("line",{x1:"18",y1:"6",x2:"6",y2:"18",style:"stroke-width: 3 !important;"}),(0,o.h)("line",{x1:"6",y1:"6",x2:"18",y2:"18",style:"stroke-width: 3 !important;"})))}async waitForT(){if(!this.props.t)return await i.Z.sleep(100),this.waitForT()}async setClose(t){if(await this.waitForT(),this.props.t){if(!t){clearTimeout(this.lastCloseTimeout),this.setState({closeAnimation:!1});let t=this.randomTimestampt(),e=i.Z.get(this.props,"plugin.notification.profiles",[]),s=e[Math.floor(Math.random()*i.Z.size(e))];s.avatar_url&&s.avatar_url.startsWith("http")&&await i.Z.preloadImg(s.avatar_url),i.Z.map(i.Z.get(this.props.plugin,"notification.custom_avatar_urls"),(t=>{e.push({type:"person",fullname:l(),avatar_url:t,email:l().split(" ").join(".").toLowerCase()+"@gmail.com",address:h(),phone:"+84"+Math.floor(10*Math.random())+Math.floor(10*Math.random())+Math.floor(10*Math.random())+Math.floor(10*Math.random())+Math.floor(10*Math.random())+Math.floor(10*Math.random())+"xxxx",age:15+Math.floor(20*Math.random())})}));let o=i.Z.get(this.props,"plugin.notification.i18n_message_quill_deltas",[]),n=o[Math.floor(Math.random()*i.Z.size(o))],a=i.Z.get(this.props,"plugin.notification.message_quill_deltas",[]),r=a[Math.floor(Math.random()*i.Z.size(a))],p=i.Z.get(this.props,"plugin.notification.i18n_title_quill_delta");return this.setState({close:!1,last_show:i.Z.Date.now(),timestamp:t,user:s,title:this.props.t.i18n(p)||i.Z.get(this.props,"plugin.notification.title_quill_delta"),message:this.props.t.i18n(n)||r})}this.setState({closeAnimation:!0}),this.mouse_leave=i.Z.Date.now(),this.lastCloseTimeout=setTimeout((()=>this.setState({close:!0,closeAnimation:!1})),150),this.props.plugin._dont_close&&setTimeout((()=>this.setState({closeAnimation:!1,close:!1})),1e3)}}async refreshCSS(){let t=this.props.store.matchPlugin();if(!i.Z.find(t,(t=>t.id===this.props.plugin.id)))return;let e=(await a).default.default.toString();i.Z.setCss(this.props.plugin.id,this.$cssStyleDiv,e),this.setClose(this.state.close)}componentWillUnmount(){clearInterval(this.interval),i.Z.setCss(this.props.plugin.id,this.$cssStyleDiv,"")}async componentDidMount(){this.setState({last_show:i.Z.Date.now()}),this.$cssStyleDiv=document.getElementById("subiz-style-for-"+this.props.plugin.id),this.$cssStyleDiv||(this.$cssStyleDiv=document.createElement("style"),document.head.appendChild(this.$cssStyleDiv),this.$cssStyleDiv.type="text/css",this.$cssStyleDiv.id="subiz-style-for-"+this.props.plugin.id),this.props.store.onResetCSS(this,(()=>this.refreshCSS())),await this.refreshCSS(),this.interval=setInterval((()=>{if(this.props._destroy)return this.componentWillUnmount();let t=this.mouse_leave;return 0===t&&(t=i.Z.Date.now()),i.Z.Date.now()-t<1e3?void 0:this.state.close||this.props.plugin._dont_close?i.Z.Date.now()-this.state.last_show>this.props.plugin.notification.interval_sec?this.setClose(!1):void 0:i.Z.Date.now()-this.state.last_show>8e3?this.setClose(!0):void 0}),1e3),setTimeout((()=>{this.setState({cssready:!0}),this.setClose(!1)}),50)}renderTextFromQuillDelta(t,e){let s=i.Z.parseJSON(t);return s&&s.ops?i.Z.map(s.ops,(t=>{let s=null;if(!t.insert)return null;if("string"==typeof t.insert&&(s=t.insert),i.Z.get(t,"insert.dynamicField")){let o=i.Z.get(t,"insert.dynamicField.key");"user.fullname"===o&&(s=e.fullname),"user.email"===o&&(s=e.email),"user.address"===o&&(s=e.address),"user.phone"===o&&(s=e.phone)}return i.Z.get(t,"attributes.bold")&&(s=(0,o.h)("b",null,s)),i.Z.get(t,"attributes.italic")&&(s=(0,o.h)("b",null,s)),s})):null}render(){if(!this.props.t)return null;if(!this.state.cssready)return null;if(!this.state.imageReady)return null;if(this.state.close)return null;if(!this.state.message)return null;let t=i.Z.get(this.props.plugin,"notification",{});if(!t)return null;let e="",s=i.Z.get(t,"position","bottom-left");this.props.mobile&&(s=i.Z.get(t,"mobile_position",s)),"top-left"===s||"top-right"===s?e="fadeInDown":"top-center"===s?e="fadeInDownCenter":"bottom-center"===s?e="fadeInUpCenter":("bottom-right"===s||(s="bottom-left"),e="fadeInUpBig");let n=this.state.user||{},a=t.subtext_style||{};void 0===a.color&&(a.color=i.Z.get(t,"message_style.color","black"));let r="position: fixed !important; z-index: 1000000000 !important";return this.props.plugin._preview&&(r="position: absolute !important;"),this.state.closeAnimation&&(e="fadeOut"),(0,o.h)("div",{class:e+" notif notif__"+s,onClick:t=>this.onClick(t),onmouseover:t=>this.setOver(!0),style:r,onmouseleave:t=>this.setOver(!1)},(0,o.h)("div",{style:"position: relative !important; display: flex !important; align-items: center !important;"},(0,o.h)("img",{alt:"notification background",class:"notif_bg",src:t.background_url,style:i.Z.js2css(t.background_style)}),this.renderCloseButton(),(0,o.h)("div",{class:"notif_avatar",style:i.Z.js2css(t.avatar_style)},(0,o.h)("img",{alt:"notification avatar",class:"notif_avatar__img",src:n.avatar_url})),(0,o.h)("div",{class:"notif_body"},(0,o.h)("div",{class:"notif_title",style:i.Z.js2css(t.title_style)},this.renderTextFromQuillDelta(this.state.title,n)),(0,o.h)("div",{class:"notif_message",style:i.Z.js2css(t.message_style)},this.renderTextFromQuillDelta(this.state.message,n)),(0,o.h)("div",{class:"notif_time",style:i.Z.js2css(t.subtext_style)},this.state.timestamp))))}}function l(){let t=["Kiều Thanh","Phương Anh","Lê Thùy Linh","Trang Nguyễn","Thanh Hoa","Hoài Đức","Huơng Giang"];return t[Math.floor(Math.random()*t.length)]}function h(){let t=["Dịch Vọng Hậu, Cầu Giấy","Quận 1, TP Hồ Chí Minh","Ngõ 34 Tôn Thất Thuyết","87 Phạm Hùng","Đống Đa, Hà Nội"];return t[Math.floor(Math.random()*t.length)]}}}]);