@subiz/widget-v4 4.1.179 → 4.1.184

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 (108) hide show
  1. package/assets/less/widget.less +40 -6
  2. package/assets/less/widget_header.less +2 -1
  3. package/chat.js +0 -1
  4. package/compiled_src/chatbox/ChatButton.js +107 -55
  5. package/compiled_src/chatbox/Widget.js +2 -1
  6. package/compiled_src/chatbox/main.js +9 -5
  7. package/compiled_src/store/store.js +33 -6
  8. package/package.json +1 -1
  9. package/src/chatbox/ChatButton.js +111 -58
  10. package/src/chatbox/Widget.js +4 -1
  11. package/src/chatbox/main.js +5 -5
  12. package/src/store/store.js +49 -18
  13. package/dist/127.js +0 -273
  14. package/dist/132.js +0 -2802
  15. package/dist/185.js +0 -1827
  16. package/dist/1991cfb4656.127.js +0 -1
  17. package/dist/1991cfb4656.132.js +0 -1
  18. package/dist/1991cfb4656.185.js +0 -1
  19. package/dist/1991cfb4656.27.js +0 -1
  20. package/dist/1991cfb4656.278.js +0 -1
  21. package/dist/1991cfb4656.339.js +0 -1
  22. package/dist/1991cfb4656.459.js +0 -1
  23. package/dist/1991cfb4656.490.js +0 -1
  24. package/dist/1991cfb4656.74.js +0 -1
  25. package/dist/1991cfb4656.997.js +0 -1
  26. package/dist/1991cfb4656.app.js +0 -1
  27. package/dist/1991cfb4656.chat.html +0 -1
  28. package/dist/1991cfb4656.chat.js +0 -1
  29. package/dist/1991cfb4656.form.html +0 -1
  30. package/dist/1991cfb4656.form.js +0 -1
  31. package/dist/1991cfb4656.index.html +0 -72
  32. package/dist/1991cfb4656.library.html +0 -72
  33. package/dist/1991cfb4656.library.js +0 -1
  34. package/dist/1991cfb4656.preview.html +0 -759
  35. package/dist/1991cfb4656.preview.js +0 -1
  36. package/dist/1991cfb4656.webview.js +0 -1
  37. package/dist/27.js +0 -107
  38. package/dist/278.js +0 -417
  39. package/dist/459.js +0 -107
  40. package/dist/490.js +0 -305
  41. package/dist/74.js +0 -372
  42. package/dist/997.js +0 -107
  43. package/dist/HASH +0 -1
  44. package/dist/assets/img/Facebook.64607ec.png +0 -0
  45. package/dist/assets/img/Zalo.6845707.png +0 -0
  46. package/dist/assets/img/award1a.1a58e10.png +0 -0
  47. package/dist/assets/img/award3a.3b74423.png +0 -0
  48. package/dist/assets/img/award4a.ed6ccd4.png +0 -0
  49. package/dist/assets/img/award5.39eb7ae.png +0 -0
  50. package/dist/assets/img/bubble_default.7d5e4ab.svg +0 -20
  51. package/dist/assets/img/caret.998eb8f.svg +0 -1
  52. package/dist/assets/img/convos_empty.2353007.svg +0 -72
  53. package/dist/assets/img/default.06e6ee0.jpg +0 -0
  54. package/dist/assets/img/default_avatar.5b74dc1.png +0 -0
  55. package/dist/assets/img/done_gray.d7e8203.svg +0 -4
  56. package/dist/assets/img/done_green.b817fd4.svg +0 -4
  57. package/dist/assets/img/emoji/messenger/sub_23.529_58.824.d5faf14.png +0 -0
  58. package/dist/assets/img/emoji/messenger/sub_23.529_60.784.1420241.png +0 -0
  59. package/dist/assets/img/emoji/messenger/sub_25.490_0.000.1e6b2c0.png +0 -0
  60. package/dist/assets/img/emoji/messenger/sub_25.490_45.098.3dfbc08.png +0 -0
  61. package/dist/assets/img/emoji/messenger/sub_25.490_5.882.4b49e94.png +0 -0
  62. package/dist/assets/img/emoji/messenger/sub_27.451_72.549.7114f58.png +0 -0
  63. package/dist/assets/img/emoji/messenger/sub_27.451_84.314.231e2b7.png +0 -0
  64. package/dist/assets/img/emoji/messenger/sub_27.451_96.078.ddbb008.png +0 -0
  65. package/dist/assets/img/emoji/messenger/sub_29.412_5.882.61f3359.png +0 -0
  66. package/dist/assets/img/emoji/messenger/sub_58.824_100.000.6df72bc.png +0 -0
  67. package/dist/assets/img/emoji/messenger/sub_58.824_45.098.3d7a7ad.png +0 -0
  68. package/dist/assets/img/emoji/messenger/sub_58.824_47.059.0f4d6e2.png +0 -0
  69. package/dist/assets/img/emoji/messenger/sub_58.824_54.902.65724c1.png +0 -0
  70. package/dist/assets/img/emoji/messenger/sub_58.824_64.706.9da3cba.png +0 -0
  71. package/dist/assets/img/emoji/messenger/sub_58.824_72.549.edca5cf.png +0 -0
  72. package/dist/assets/img/emoji/messenger/sub_58.824_78.431.f910f2a.png +0 -0
  73. package/dist/assets/img/emoji/messenger/sub_58.824_88.235.def4e71.png +0 -0
  74. package/dist/assets/img/emoji/messenger/sub_60.784_11.765.49c03d0.png +0 -0
  75. package/dist/assets/img/emoji/messenger/sub_60.784_27.451.46b54e5.png +0 -0
  76. package/dist/assets/img/emoji/messenger/sub_60.784_29.412.e36d284.png +0 -0
  77. package/dist/assets/img/emoji/messenger/sub_60.784_3.922.bb191b0.png +0 -0
  78. package/dist/assets/img/emoji/messenger/sub_60.784_35.294.af7b927.png +0 -0
  79. package/dist/assets/img/emoji/messenger/sub_60.784_7.843.98f2a99.png +0 -0
  80. package/dist/assets/img/empty.29bed2d.svg +0 -23
  81. package/dist/assets/img/empty_1.0b98af0.svg +0 -11
  82. package/dist/assets/img/examplte_logo.f86535f.svg +0 -1
  83. package/dist/assets/img/external-link.90577cc.svg +0 -1
  84. package/dist/assets/img/fb_inverse_circle.36c2cfc.png +0 -0
  85. package/dist/assets/img/ghn.070f8e3.svg +0 -17
  86. package/dist/assets/img/ghtk.326eac1.svg +0 -18
  87. package/dist/assets/img/image_default.be0698b.png +0 -0
  88. package/dist/assets/img/info.ebce7ea.svg +0 -1
  89. package/dist/assets/img/loader.37000a7.svg +0 -1
  90. package/dist/assets/img/loading_static.a27f0ac.svg +0 -10
  91. package/dist/assets/img/main-service1.d536cc2.png +0 -0
  92. package/dist/assets/img/main-service2.9b99549.png +0 -0
  93. package/dist/assets/img/not_found_search.2ddb8d1.png +0 -0
  94. package/dist/assets/img/package.8d37d0f.svg +0 -5
  95. package/dist/assets/img/package_fade.763c001.svg +0 -1
  96. package/dist/assets/img/rating--average.1ea492c.svg +0 -12
  97. package/dist/assets/img/rating--great.e3d712e.svg +0 -16
  98. package/dist/assets/img/rating--poor.2938a25.svg +0 -12
  99. package/dist/assets/img/search.f9705ff.svg +0 -1
  100. package/dist/assets/img/send.6db52a9.svg +0 -3
  101. package/dist/assets/img/shop.f7dc7d8.svg +0 -1
  102. package/dist/assets/img/shop_faded.df7845a.svg +0 -1
  103. package/dist/assets/img/stars_v2.79cf728.png +0 -0
  104. package/dist/assets/img/subiz-mono.8fbc067.svg +0 -3
  105. package/dist/assets/img/x.26fdfa3.svg +0 -5
  106. package/dist/malicious-app.js +0 -17
  107. package/dist/screenshoot.html +0 -7
  108. package/dist/screenshoot.js +0 -11988
@@ -9,10 +9,15 @@ import {h} from 'preact'
9
9
  export default class ChatButton extends Com {
10
10
  constructor(props) {
11
11
  super(props)
12
- this.setState({
13
- opacity: 0, // wait for image to load first before setting opacity to 1
14
- })
15
- this.loadGreeting()
12
+ this.state = {
13
+ hasPreviewDom: false,
14
+ previewExtraCls: 'hidden',
15
+ previewEvent: {},
16
+ ready: false,
17
+ }
18
+
19
+ this.readyGate = new sb.Gate()
20
+ this.prepareButtonImage()
16
21
 
17
22
  this.props.store.onUpdate(this, (_) => this.forceUpdate())
18
23
  this.props.store.onConvoEvent(this, (ev) => {
@@ -53,6 +58,17 @@ export default class ChatButton extends Com {
53
58
  this.props.store.updateLastview({screen: 'preview', previewEvent: ev})
54
59
  this.forceUpdate()
55
60
  })
61
+ this.props.store.onLastview(this, () => {
62
+ let screen = sb.get(this.props.store.matchLastview(), 'screen')
63
+ let previewEvent = sb.get(this.props.store.matchLastview(), 'previewEvent') || {}
64
+ let isOpen = screen === 'preview' && sb.size(previewEvent) > 0
65
+ if (isOpen) {
66
+ this.makeAnimateShowPreview(previewEvent)
67
+ } else {
68
+ this.makeAnimateHidePreview()
69
+ }
70
+ })
71
+ this.loadGreeting()
56
72
  }
57
73
 
58
74
  fixMissingSetting(chatbox) {
@@ -94,14 +110,12 @@ export default class ChatButton extends Com {
94
110
  if (hiddenButtonDesktop) return null
95
111
 
96
112
  let cls = 'widget-layout widget-layout--' + position
97
- let opacity = this.state.opacity
98
113
  if (!this.props.isShow) {
99
114
  cls += ' widget-layout--hidden'
100
- opacity = 0
101
115
  }
102
116
 
103
117
  return (
104
- <div class={cls} style={'opacity: ' + opacity + ' !important'}>
118
+ <div class={cls}>
105
119
  {this.renderPreview()}
106
120
  {this.renderButton()}
107
121
  </div>
@@ -136,46 +150,71 @@ export default class ChatButton extends Com {
136
150
  return unseenConvo[0].last_message_sent
137
151
  }
138
152
 
153
+ showPreview(ev) {
154
+ this.props.store.updateLastview({screen: 'preview', previewEvent: ev})
155
+ }
156
+
157
+ async makeAnimateShowPreview(ev) {
158
+ await this.readyGate.entry()
159
+ let agent = this.getAgentOfPreviewEvent(ev)
160
+ await sb.preloadImg(agent.avatar_url)
161
+ if (this.state.hasPreviewDom) {
162
+ this.setState({previewExtraCls: 'hidden'})
163
+ if (this._animateTimeout) clearTimeout(this._animateTimeout)
164
+ this._animateTimeout = setTimeout(() => {
165
+ this.setState({previewExtraCls: '', previewEvent: ev})
166
+ }, 200)
167
+ return
168
+ }
169
+ this.setState({
170
+ hasPreviewDom: true,
171
+ previewExtraCls: 'hidden',
172
+ previewEvent: {},
173
+ })
174
+ if (this._animateTimeout) clearTimeout(this._animateTimeout)
175
+ this._animateTimeout = setTimeout(() => {
176
+ this.setState({previewExtraCls: '', previewEvent: ev})
177
+ }, 200)
178
+ }
179
+
180
+ makeAnimateHidePreview() {
181
+ if (this._animateTimeout) clearTimeout(this._animateTimeout)
182
+ this.setState({previewExtraCls: 'hidden'})
183
+ this._animateTimeout = setTimeout(() => {
184
+ this.setState({hasPreviewDom: false, previewEvent: {}})
185
+ }, 200)
186
+ }
187
+
139
188
  // this method could be call from the parent
140
189
  ShowGreeting() {
141
- this.props.store.updateLastview({screen: 'preview', previewEvent: this.pickBestGreeting()})
142
- this.forceUpdate()
143
- //this.setState({
144
- //previewEvent: this.pickBestGreeting(),
145
- //})
190
+ let ev = this.pickBestGreeting()
191
+ this.showPreview(ev)
146
192
  }
147
193
 
148
194
  HideGreeting() {
149
195
  this.props.store.updateLastview({screen: 'button', minimized: Date.now(), previewEvent: {}})
150
- this.forceUpdate()
151
- //this.setState({previewEvent: {}})
152
196
  }
153
197
 
154
198
  loadGreeting() {
155
199
  let minimized = sb.get(this.props.store.matchLastview(), 'minimized')
156
200
  let screen = sb.get(this.props.store.matchLastview(), 'screen')
157
- console.log('loadGreeting matchLastview', this.props.store.matchLastview())
158
201
  if (screen !== 'preview') return
159
202
  if (minimized && Date.now() - minimized < Ms30Mins) return
203
+ let previewEvent = sb.get(this.props.store.matchLastview(), 'previewEvent') || {}
204
+ if (sb.size(previewEvent) > 0) {
205
+ this.showPreview(previewEvent)
206
+ return
207
+ }
208
+
160
209
  let accountSetting = this.props.plugin.chatbox
161
- // dont show preview if the user has previously closed it
162
210
 
163
211
  let greeting = sb.get(accountSetting, 'greeting', {})
164
212
  let text = this.props.t.i18n(sb.get(greeting, 'greeting', {})) || greeting.message
165
213
 
166
214
  let enabled = greeting.enabled
167
- if (this.props.store.isMobile()) {
168
- enabled = enabled && !sb.get(greeting, 'mobile_disabled')
169
- // dont show greeting fro mobile anymore
170
- this.props.store.updateLastview({screen: 'button', previewEvent: {}})
171
- return
172
- }
173
215
  if (!text || !enabled) {
174
- this.props.store.updateLastview({screen: 'button', previewEvent: {}})
175
- this.forceUpdate()
176
216
  return
177
217
  }
178
- console.log('loadGreeting pickBestGreeting', this.pickBestGreeting())
179
218
  this.ShowGreeting()
180
219
  }
181
220
 
@@ -206,7 +245,6 @@ export default class ChatButton extends Com {
206
245
  if (!convo) convo = convos[0] || {}
207
246
  cid = convo.id
208
247
  }
209
- //this.HideGreeting()
210
248
  this.props.onClick && this.props.onClick({view: 'chat', cid})
211
249
  }
212
250
 
@@ -216,11 +254,10 @@ export default class ChatButton extends Com {
216
254
  return <div class='chat-button--unread'>{unreadcount}</div>
217
255
  }
218
256
 
219
- renderPreview() {
257
+ getAgentOfPreviewEvent(ev) {
220
258
  let account = this.props.store.matchAccount()
221
- if (!account) return null
222
259
  let accountSetting = this.props.plugin.chatbox
223
- let previewEvent = sb.get(this.props.store.matchLastview(), 'previewEvent') || {}
260
+ let previewEvent = ev
224
261
  let byid = sb.get(previewEvent, 'by.display_id', sb.get(previewEvent, 'by.id'))
225
262
  // let agent = sb.cloneDeep(this.props.store.matchAgent(byid)) || {}
226
263
  // somehow store.matchAgent(id) return undefined so we try to backup with store.matchAgent('*')[id]
@@ -229,10 +266,6 @@ export default class ChatButton extends Com {
229
266
  agent = sb.cloneDeep(agent)
230
267
  agent.fullname = agent.fullname || sb.get(account, 'name') || this.props.t('agent')
231
268
  agent.avatar_url = agent.avatar_url || account.logo_url || require('../../assets/img/image_default.png')
232
- let position = sb.get(accountSetting, 'desktop_button.position') || 'right'
233
- if (this.props.store.isMobile()) {
234
- position = sb.get(accountSetting, 'mobile_button.position') || position
235
- }
236
269
 
237
270
  if (accountSetting && accountSetting.hide_agent_profile) {
238
271
  agent = Object.assign({}, account, {
@@ -241,6 +274,22 @@ export default class ChatButton extends Com {
241
274
  })
242
275
  }
243
276
 
277
+ return agent
278
+ }
279
+
280
+ renderPreview() {
281
+ if (this.props.store.isMobile()) return
282
+ if (!this.state.hasPreviewDom) return
283
+ let previewEvent = this.state.previewEvent
284
+ let agent = this.getAgentOfPreviewEvent(previewEvent)
285
+
286
+ let account = this.props.store.matchAccount()
287
+ let accountSetting = this.props.plugin.chatbox
288
+ let position = sb.get(accountSetting, 'desktop_button.position') || 'right'
289
+ if (this.props.store.isMobile()) {
290
+ position = sb.get(accountSetting, 'mobile_button.position') || position
291
+ }
292
+
244
293
  let tags = this.renderMessagePreview(previewEvent)
245
294
  let attachments = sb.get(previewEvent, 'data.message.attachments') || []
246
295
  let quickReplies = sb.find(attachments, (att) => att.type === 'quick_replies')
@@ -257,10 +306,8 @@ export default class ChatButton extends Com {
257
306
  uri = this.props.store.FileURL + uri
258
307
  }
259
308
 
260
- let isShowPreview = sb.get(this.props.store.matchLastview(), 'screen') === 'preview'
261
-
262
309
  return (
263
- <div class={`widget-preview-new-wrapper ${isShowPreview ? '' : 'hidden'}`}>
310
+ <div class={`widget-preview-new-wrapper ${this.state.previewExtraCls}`}>
264
311
  <div class={`widget-preview-x-wrapper ${position}`}>
265
312
  <div class='widget-preview--btn-close' onClick={(e) => this.closePreview(e)} />
266
313
  </div>
@@ -270,15 +317,15 @@ export default class ChatButton extends Com {
270
317
  alt='widget avatar'
271
318
  class='widget-preview--avatar'
272
319
  src={this.props.store.replaceFileUrl(agent.avatar_url)}
273
- onError={(ev) => this.onProfileError(ev)}
274
- onload={(_) => this.onProfileReady()}
275
320
  />
276
321
  <div class='widget-preview-text-message--author'>
277
322
  <div class='widget-preview-text-message--author-text'>{agent.fullname}</div>
278
- <div class='badge badge--success'>
279
- <div class='dot dot--success mr-1' />
280
- {'ONLINE'}
281
- </div>
323
+ {accountSetting.is_online && (
324
+ <div class='badge badge--success'>
325
+ <div class='dot dot--success mr-1' />
326
+ {'ONLINE'}
327
+ </div>
328
+ )}
282
329
  </div>
283
330
  </div>
284
331
  <div class='widget-preview-text-message--content'>{tags}</div>
@@ -293,6 +340,7 @@ export default class ChatButton extends Com {
293
340
  {sb.size(quickReplies) > 0 && (
294
341
  <div class={`widget-preview-quick-reply-wrapper ${position}`}>
295
342
  {sb.map(quickReplies, (reply) => {
343
+ if (!(reply.title || '').trim()) return
296
344
  return (
297
345
  <div
298
346
  class='widget-preview-quick-reply-item'
@@ -324,14 +372,25 @@ export default class ChatButton extends Com {
324
372
  )
325
373
  }
326
374
 
327
- onProfileReady() {
328
- if (this._buttonLoaded) this.setState({opacity: 1})
329
- this._profileLoaded = true
330
- }
375
+ async prepareButtonImage() {
376
+ let accountSetting = this.props.plugin.chatbox
377
+ accountSetting = this.fixMissingSetting(accountSetting)
378
+ let imgsrc =
379
+ sb.get(accountSetting, 'desktop_button.background_image_url') ||
380
+ sb.get(accountSetting, 'desktop_button.background_mask_url') ||
381
+ defaultBubble
331
382
 
332
- onButtonReady() {
333
- if (this._profileLoaded) this.setState({opacity: 1})
334
- this._buttonLoaded = true
383
+ if (this.props.store.isMobile()) {
384
+ imgsrc =
385
+ sb.get(accountSetting, 'mobile_button.background_image_url') ||
386
+ sb.get(accountSetting, 'mobile_button.background_mask_url') ||
387
+ imgsrc
388
+ }
389
+
390
+ imgsrc = this.props.store.replaceFileUrl(imgsrc)
391
+ await sb.preloadImg(imgsrc)
392
+ this.setState({ready: true})
393
+ this.readyGate.open()
335
394
  }
336
395
 
337
396
  renderButton() {
@@ -441,19 +500,13 @@ export default class ChatButton extends Com {
441
500
 
442
501
  `
443
502
 
503
+ if (!this.state.ready) cls += ' hidden'
504
+
444
505
  return (
445
506
  <div class={cls} onClick={(e) => this.onClick(e)}>
446
507
  <div class={whitebgcls} style={whiteBgStyle}></div>
447
508
  <div class='chat-button--img-container' style={imgcontainerstyle}>
448
- <img
449
- width='70'
450
- height='70'
451
- alt='chat button'
452
- class='chat-button--img'
453
- onload={() => this.onButtonReady()}
454
- src={imgsrc}
455
- onError={(e, a) => this.onChatButtonError(e, a)}
456
- />
509
+ <img width='70' height='70' alt='chat button' class='chat-button--img' src={imgsrc} />
457
510
  </div>
458
511
  {this.renderUnread()}
459
512
  </div>
@@ -46,6 +46,7 @@ export default class Widget extends Com {
46
46
  msgInput = createRef()
47
47
  componentDidMount() {
48
48
  if (!this.props.store.isMobile()) this.focusInput()
49
+
49
50
  this.updateFormDataFields()
50
51
  }
51
52
 
@@ -131,8 +132,10 @@ export default class Widget extends Com {
131
132
  else $body = this.renderChat()
132
133
 
133
134
  let position = sb.get(accountSetting, 'desktop_button.position') || 'right'
134
- if (this.props.store.isMobile()) position = sb.get(accountSetting, 'mobile_button.position', position)
135
+ if (this.props.store.isMobile() || this.props.store.isEmbededChatMode())
136
+ position = sb.get(accountSetting, 'mobile_button.position', position)
135
137
  let cls = 'widget-container widget-container--' + position
138
+ if (this.props.store.isEmbededChatMode()) cls += ' embed-chat'
136
139
  if (!this.props.store.isMobile() && sb.get(accountSetting, 'window_mode') === 'full')
137
140
  cls += ' widget-container--full'
138
141
  if (!this.props.isShow) cls += ' widget-container--hide'
@@ -81,7 +81,7 @@ export default class Main extends Com {
81
81
  let widgetConvoId = sb.get(lastview, 'opts.cid')
82
82
 
83
83
  return (
84
- <div class={this.props.store.isMobile() ? 'mobile' : 'desktop'}>
84
+ <div class={this.props.store.isMobile() || this.props.store.isEmbededChatMode() ? 'mobile' : 'desktop'}>
85
85
  <ChatButton
86
86
  plugin={this.props.plugin}
87
87
  store={this.props.store}
@@ -153,16 +153,16 @@ export default class Main extends Com {
153
153
  async showWidget(p) {
154
154
  //this.refButton.current && this.refButton.current.ClearPreview()
155
155
 
156
- let cid = p.cid
157
- let newView = {screen: 'widget', minimized: 0, view: p.view}
156
+ let cid = p.cid
157
+ let newView = {screen: 'widget', minimized: 0, view: p.view, previewEvent: {}, opts: {cid}}
158
158
  if (!p.view && !p.cid) {
159
159
  let convoM = this.props.store.matchConvo('*')
160
160
  let redconvo = sb.find(convoM, (convo) => !sb.isConvoSeen(convo, this.props.store.matchUser().id))
161
161
  // try to show first convo
162
162
  cid = sb.get(redconvo, 'id', sb.get(convoM, '0.id'))
163
- newView.view = 'chat'
163
+ newView.view = 'chat'
164
+ newView.opts = {cid}
164
165
  }
165
- if (cid) newView.opts = {cid}
166
166
 
167
167
  if (this.props.store.isMobile()) modifyViewport()
168
168
  this.props.store.updateLastview(newView)
@@ -359,6 +359,27 @@ export default class Store {
359
359
  }
360
360
 
361
361
  matchPlugin = () => {
362
+ if (this.is_embed_chat_mode) {
363
+ // only show widget
364
+ let pluginM = this.cache.match('plugin')
365
+ if (sb.size(this.forcePlugins) > 0) pluginM = this.forcePlugins
366
+
367
+ let chatboxs = sb.filter(pluginM, (plugin, id) => plugin && plugin.type === 'chatbox')
368
+ if (sb.size(chatboxs) === 0) {
369
+ console.error('no chatbox found.')
370
+ return
371
+ }
372
+
373
+ let chatbox = sb.find(chatboxs, (chatbox) => !!chatbox)
374
+ if (!chatbox) {
375
+ // take the first chatbox
376
+ chatbox = chatboxs[0]
377
+ }
378
+
379
+ chatbox = sb.cloneDeep(chatbox)
380
+ chatbox.triggers = undefined
381
+ return {[chatbox.id]: chatbox}
382
+ }
362
383
  if (sb.size(this.forcePlugins) > 0) return sb.cloneDeep(this.forcePlugins)
363
384
  return sb.cloneDeep(this.cache.match('plugin')) || {}
364
385
  }
@@ -462,22 +483,7 @@ export default class Store {
462
483
 
463
484
  // last widget screen
464
485
  matchLastview = () => {
465
- let lastView = this.kv.match('lastview') || {}
466
-
467
- // make sure last view of correct user
468
- let user = this.cache.match('user') || {}
469
- if (!user.id) return { screen: 'preview' }
470
- if (lastView.user_id != user.id) return { screen: 'preview' }
471
-
472
- if (!lastView.screen) {
473
- lastView.screen = 'preview' // mode preview allow load default greeting
474
-
475
- // backward compatible for user currently view chat
476
- if (lastView.view === 'list' || lastView.view === 'chat') {
477
- lastView.screen = 'widget'
478
- }
479
- }
480
- return lastView
486
+ return this.kv.match('lastview') || {}
481
487
  }
482
488
 
483
489
  matchIsOpen = () => !!this.kv.match('isopen') // is widget currently open
@@ -571,6 +577,28 @@ export default class Store {
571
577
  )
572
578
  }
573
579
 
580
+ standardlizeLastview() {
581
+ let lastView = this.kv.match('lastview') || {}
582
+
583
+ // make sure last view of correct user
584
+ let user = this.cache.match('user') || {}
585
+ if (!user.id) lastView = {}
586
+ if (lastView.user_id != user.id) lastView = {}
587
+
588
+ if (!lastView.screen) {
589
+ lastView.screen = 'preview' // mode preview allow load default greeting
590
+
591
+ // backward compatible for user currently view chat
592
+ if (lastView.view === 'list' || lastView.view === 'chat') {
593
+ lastView.screen = 'widget'
594
+ }
595
+ }
596
+
597
+ // mobile always has screen button initially
598
+ if (this.isMobile()) lastView.screen = 'button'
599
+ this.kv.put('lastview', lastView)
600
+ }
601
+
574
602
  async _initResource(accid, auth, realtimep) {
575
603
  this.g_sync = {}
576
604
 
@@ -599,6 +627,7 @@ export default class Store {
599
627
  this.seenLoop()
600
628
  if (typeof sbz_info != 'undefined') sbz_info.store_9 = true
601
629
  await this.reconnect({user: user}) // already fetched
630
+ this.standardlizeLastview()
602
631
  if (typeof sbz_info != 'undefined') sbz_info.store_10 = true
603
632
  this.readyGate.open()
604
633
  this.reconnectWs(accid, user.id)
@@ -1225,14 +1254,16 @@ export default class Store {
1225
1254
  let user = this.cache.match('user') || {}
1226
1255
  if (!user.id) return // store not init
1227
1256
  let lastview = this.matchLastview() || {}
1228
- lastview = {
1257
+ let newview = {
1229
1258
  ...lastview,
1230
1259
  ...obj,
1231
1260
  user_id: user.id,
1232
1261
  }
1233
1262
 
1234
- this.kv.put('lastview', lastview)
1263
+ this.kv.put('lastview', newview)
1264
+ this.pubsub.publish('lastview', newview, lastview)
1235
1265
  }
1266
+ onLastview = (o, cb) => this.pubsub.on2(o, 'lastview', cb)
1236
1267
 
1237
1268
  matchLastPluginRun(pluginid) {
1238
1269
  let log = this.kv.match('plugin_run_logs') || {}