@subiz/widget-v4 4.1.178 → 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.
- package/assets/less/base.less +28 -0
- package/assets/less/chatbox.less +4 -0
- package/assets/less/message.less +0 -8
- package/assets/less/widget.less +197 -2
- package/assets/less/widget_header.less +2 -1
- package/chat.js +0 -1
- package/compiled_src/chatbox/ChatButton.js +183 -82
- package/compiled_src/chatbox/Widget.js +2 -1
- package/compiled_src/chatbox/main.js +44 -53
- package/compiled_src/store/store.js +40 -17
- package/package.json +5 -5
- package/src/chatbox/ChatButton.js +197 -77
- package/src/chatbox/Widget.js +4 -2
- package/src/chatbox/main.js +30 -52
- package/src/store/store.js +56 -18
- package/dist/127.js +0 -273
- package/dist/132.js +0 -2802
- package/dist/185.js +0 -1827
- package/dist/1991cfb4656.127.js +0 -1
- package/dist/1991cfb4656.132.js +0 -1
- package/dist/1991cfb4656.185.js +0 -1
- package/dist/1991cfb4656.27.js +0 -1
- package/dist/1991cfb4656.278.js +0 -1
- package/dist/1991cfb4656.339.js +0 -1
- package/dist/1991cfb4656.459.js +0 -1
- package/dist/1991cfb4656.490.js +0 -1
- package/dist/1991cfb4656.74.js +0 -1
- package/dist/1991cfb4656.997.js +0 -1
- package/dist/1991cfb4656.app.js +0 -1
- package/dist/1991cfb4656.chat.html +0 -1
- package/dist/1991cfb4656.chat.js +0 -1
- package/dist/1991cfb4656.form.html +0 -1
- package/dist/1991cfb4656.form.js +0 -1
- package/dist/1991cfb4656.index.html +0 -72
- package/dist/1991cfb4656.library.html +0 -72
- package/dist/1991cfb4656.library.js +0 -1
- package/dist/1991cfb4656.preview.html +0 -759
- package/dist/1991cfb4656.preview.js +0 -1
- package/dist/1991cfb4656.webview.js +0 -1
- package/dist/27.js +0 -107
- package/dist/278.js +0 -417
- package/dist/459.js +0 -107
- package/dist/490.js +0 -305
- package/dist/74.js +0 -372
- package/dist/997.js +0 -107
- package/dist/HASH +0 -1
- package/dist/assets/img/Facebook.64607ec.png +0 -0
- package/dist/assets/img/Zalo.6845707.png +0 -0
- package/dist/assets/img/award1a.1a58e10.png +0 -0
- package/dist/assets/img/award3a.3b74423.png +0 -0
- package/dist/assets/img/award4a.ed6ccd4.png +0 -0
- package/dist/assets/img/award5.39eb7ae.png +0 -0
- package/dist/assets/img/bubble_default.7d5e4ab.svg +0 -20
- package/dist/assets/img/caret.998eb8f.svg +0 -1
- package/dist/assets/img/convos_empty.2353007.svg +0 -72
- package/dist/assets/img/default.06e6ee0.jpg +0 -0
- package/dist/assets/img/default_avatar.5b74dc1.png +0 -0
- package/dist/assets/img/done_gray.d7e8203.svg +0 -4
- package/dist/assets/img/done_green.b817fd4.svg +0 -4
- package/dist/assets/img/emoji/messenger/sub_23.529_58.824.d5faf14.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_23.529_60.784.1420241.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_25.490_0.000.1e6b2c0.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_25.490_45.098.3dfbc08.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_25.490_5.882.4b49e94.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_27.451_72.549.7114f58.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_27.451_84.314.231e2b7.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_27.451_96.078.ddbb008.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_29.412_5.882.61f3359.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_100.000.6df72bc.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_45.098.3d7a7ad.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_47.059.0f4d6e2.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_54.902.65724c1.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_64.706.9da3cba.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_72.549.edca5cf.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_78.431.f910f2a.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_88.235.def4e71.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_11.765.49c03d0.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_27.451.46b54e5.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_29.412.e36d284.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_3.922.bb191b0.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_35.294.af7b927.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_7.843.98f2a99.png +0 -0
- package/dist/assets/img/empty.29bed2d.svg +0 -23
- package/dist/assets/img/empty_1.0b98af0.svg +0 -11
- package/dist/assets/img/examplte_logo.f86535f.svg +0 -1
- package/dist/assets/img/external-link.90577cc.svg +0 -1
- package/dist/assets/img/fb_inverse_circle.36c2cfc.png +0 -0
- package/dist/assets/img/ghn.070f8e3.svg +0 -17
- package/dist/assets/img/ghtk.326eac1.svg +0 -18
- package/dist/assets/img/image_default.be0698b.png +0 -0
- package/dist/assets/img/info.ebce7ea.svg +0 -1
- package/dist/assets/img/loader.37000a7.svg +0 -1
- package/dist/assets/img/loading_static.a27f0ac.svg +0 -10
- package/dist/assets/img/main-service1.d536cc2.png +0 -0
- package/dist/assets/img/main-service2.9b99549.png +0 -0
- package/dist/assets/img/not_found_search.2ddb8d1.png +0 -0
- package/dist/assets/img/package.8d37d0f.svg +0 -5
- package/dist/assets/img/package_fade.763c001.svg +0 -1
- package/dist/assets/img/rating--average.1ea492c.svg +0 -12
- package/dist/assets/img/rating--great.e3d712e.svg +0 -16
- package/dist/assets/img/rating--poor.2938a25.svg +0 -12
- package/dist/assets/img/search.f9705ff.svg +0 -1
- package/dist/assets/img/send.6db52a9.svg +0 -3
- package/dist/assets/img/shop.f7dc7d8.svg +0 -1
- package/dist/assets/img/shop_faded.df7845a.svg +0 -1
- package/dist/assets/img/stars_v2.79cf728.png +0 -0
- package/dist/assets/img/subiz-mono.8fbc067.svg +0 -3
- package/dist/assets/img/x.26fdfa3.svg +0 -5
- package/dist/malicious-app.js +0 -17
- package/dist/screenshoot.html +0 -7
- package/dist/screenshoot.js +0 -11988
|
@@ -9,12 +9,15 @@ import {h} from 'preact'
|
|
|
9
9
|
export default class ChatButton extends Com {
|
|
10
10
|
constructor(props) {
|
|
11
11
|
super(props)
|
|
12
|
-
this.
|
|
13
|
-
|
|
12
|
+
this.state = {
|
|
13
|
+
hasPreviewDom: false,
|
|
14
|
+
previewExtraCls: 'hidden',
|
|
14
15
|
previewEvent: {},
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
16
|
+
ready: false,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
this.readyGate = new sb.Gate()
|
|
20
|
+
this.prepareButtonImage()
|
|
18
21
|
|
|
19
22
|
this.props.store.onUpdate(this, (_) => this.forceUpdate())
|
|
20
23
|
this.props.store.onConvoEvent(this, (ev) => {
|
|
@@ -39,9 +42,33 @@ export default class ChatButton extends Com {
|
|
|
39
42
|
let message = sb.get(ev, 'data.message.text') || ''
|
|
40
43
|
if (!message && isquickreplies) return
|
|
41
44
|
}
|
|
45
|
+
let screen = sb.get(this.props.store.matchLastview(), 'screen')
|
|
46
|
+
let minimized = sb.get(this.props.store.matchLastview(), 'minimized')
|
|
47
|
+
if (screen === 'widget') return
|
|
48
|
+
if (minimized && Date.now() - minimized < Ms30Mins) return
|
|
42
49
|
|
|
43
|
-
this.
|
|
50
|
+
if (this.props.store.isMobile()) {
|
|
51
|
+
// dont show greeting fro mobile anymore
|
|
52
|
+
// need setState previewEvent for display 1 unread in mobile
|
|
53
|
+
this.props.store.updateLastview({previewEvent: ev})
|
|
54
|
+
this.forceUpdate()
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.props.store.updateLastview({screen: 'preview', previewEvent: ev})
|
|
59
|
+
this.forceUpdate()
|
|
44
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()
|
|
45
72
|
}
|
|
46
73
|
|
|
47
74
|
fixMissingSetting(chatbox) {
|
|
@@ -83,29 +110,18 @@ export default class ChatButton extends Com {
|
|
|
83
110
|
if (hiddenButtonDesktop) return null
|
|
84
111
|
|
|
85
112
|
let cls = 'widget-layout widget-layout--' + position
|
|
86
|
-
let opacity = this.state.opacity
|
|
87
113
|
if (!this.props.isShow) {
|
|
88
114
|
cls += ' widget-layout--hidden'
|
|
89
|
-
opacity = 0
|
|
90
115
|
}
|
|
91
116
|
|
|
92
117
|
return (
|
|
93
|
-
<div class={cls}
|
|
118
|
+
<div class={cls}>
|
|
94
119
|
{this.renderPreview()}
|
|
95
120
|
{this.renderButton()}
|
|
96
121
|
</div>
|
|
97
122
|
)
|
|
98
123
|
}
|
|
99
124
|
|
|
100
|
-
// this method could be call from the parent
|
|
101
|
-
ClearPreview() {
|
|
102
|
-
this.setState({previewEvent: {}})
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
ClosePreview() {
|
|
106
|
-
this.setState({displayPreview: false})
|
|
107
|
-
}
|
|
108
|
-
|
|
109
125
|
pickBestGreeting() {
|
|
110
126
|
let convoM = this.props.store.matchConvo('*')
|
|
111
127
|
let unseenConvo = sb
|
|
@@ -134,32 +150,69 @@ export default class ChatButton extends Com {
|
|
|
134
150
|
return unseenConvo[0].last_message_sent
|
|
135
151
|
}
|
|
136
152
|
|
|
137
|
-
|
|
138
|
-
|
|
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
|
+
}
|
|
139
169
|
this.setState({
|
|
140
|
-
|
|
141
|
-
|
|
170
|
+
hasPreviewDom: true,
|
|
171
|
+
previewExtraCls: 'hidden',
|
|
172
|
+
previewEvent: {},
|
|
142
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
|
+
|
|
188
|
+
// this method could be call from the parent
|
|
189
|
+
ShowGreeting() {
|
|
190
|
+
let ev = this.pickBestGreeting()
|
|
191
|
+
this.showPreview(ev)
|
|
143
192
|
}
|
|
144
193
|
|
|
145
194
|
HideGreeting() {
|
|
146
|
-
this.
|
|
195
|
+
this.props.store.updateLastview({screen: 'button', minimized: Date.now(), previewEvent: {}})
|
|
147
196
|
}
|
|
148
197
|
|
|
149
198
|
loadGreeting() {
|
|
199
|
+
let minimized = sb.get(this.props.store.matchLastview(), 'minimized')
|
|
200
|
+
let screen = sb.get(this.props.store.matchLastview(), 'screen')
|
|
201
|
+
if (screen !== 'preview') return
|
|
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
|
+
|
|
150
209
|
let accountSetting = this.props.plugin.chatbox
|
|
151
|
-
// dont show preview if the user has previously closed it
|
|
152
|
-
if (new sb.Date().getTime() - this.props.store.matchClosePreviewAt() < Ms30Mins) return
|
|
153
210
|
|
|
154
211
|
let greeting = sb.get(accountSetting, 'greeting', {})
|
|
155
212
|
let text = this.props.t.i18n(sb.get(greeting, 'greeting', {})) || greeting.message
|
|
156
213
|
|
|
157
214
|
let enabled = greeting.enabled
|
|
158
|
-
if (this.props.store.isMobile()) {
|
|
159
|
-
enabled = enabled && !sb.get(greeting, 'mobile_disabled')
|
|
160
|
-
}
|
|
161
215
|
if (!text || !enabled) {
|
|
162
|
-
this.setState({previewEvent: {}})
|
|
163
216
|
return
|
|
164
217
|
}
|
|
165
218
|
this.ShowGreeting()
|
|
@@ -184,14 +237,14 @@ export default class ChatButton extends Com {
|
|
|
184
237
|
}
|
|
185
238
|
|
|
186
239
|
onPreviewClick(e) {
|
|
187
|
-
let
|
|
240
|
+
let previewEvent = sb.get(this.props.store.matchLastview(), 'previewEvent') || {}
|
|
241
|
+
let cid = sb.convoOfEv(previewEvent)
|
|
188
242
|
if (!cid) {
|
|
189
243
|
let convos = sb.map(this.props.store.matchConvo('*'))
|
|
190
244
|
let convo = sb.find(convos, (convo) => !sb.isConvoSeen(convo, this.props.store.matchUser().id))
|
|
191
245
|
if (!convo) convo = convos[0] || {}
|
|
192
246
|
cid = convo.id
|
|
193
247
|
}
|
|
194
|
-
this.closePreview(e)
|
|
195
248
|
this.props.onClick && this.props.onClick({view: 'chat', cid})
|
|
196
249
|
}
|
|
197
250
|
|
|
@@ -201,11 +254,11 @@ export default class ChatButton extends Com {
|
|
|
201
254
|
return <div class='chat-button--unread'>{unreadcount}</div>
|
|
202
255
|
}
|
|
203
256
|
|
|
204
|
-
|
|
257
|
+
getAgentOfPreviewEvent(ev) {
|
|
205
258
|
let account = this.props.store.matchAccount()
|
|
206
|
-
if (!account) return null
|
|
207
259
|
let accountSetting = this.props.plugin.chatbox
|
|
208
|
-
let
|
|
260
|
+
let previewEvent = ev
|
|
261
|
+
let byid = sb.get(previewEvent, 'by.display_id', sb.get(previewEvent, 'by.id'))
|
|
209
262
|
// let agent = sb.cloneDeep(this.props.store.matchAgent(byid)) || {}
|
|
210
263
|
// somehow store.matchAgent(id) return undefined so we try to backup with store.matchAgent('*')[id]
|
|
211
264
|
let agent = this.props.store.matchAgent(byid)
|
|
@@ -213,10 +266,6 @@ export default class ChatButton extends Com {
|
|
|
213
266
|
agent = sb.cloneDeep(agent)
|
|
214
267
|
agent.fullname = agent.fullname || sb.get(account, 'name') || this.props.t('agent')
|
|
215
268
|
agent.avatar_url = agent.avatar_url || account.logo_url || require('../../assets/img/image_default.png')
|
|
216
|
-
let position = sb.get(accountSetting, 'desktop_button.position') || 'right'
|
|
217
|
-
if (this.props.store.isMobile()) {
|
|
218
|
-
position = sb.get(accountSetting, 'mobile_button.position') || position
|
|
219
|
-
}
|
|
220
269
|
|
|
221
270
|
if (accountSetting && accountSetting.hide_agent_profile) {
|
|
222
271
|
agent = Object.assign({}, account, {
|
|
@@ -225,44 +274,123 @@ export default class ChatButton extends Com {
|
|
|
225
274
|
})
|
|
226
275
|
}
|
|
227
276
|
|
|
228
|
-
|
|
229
|
-
|
|
277
|
+
return agent
|
|
278
|
+
}
|
|
230
279
|
|
|
231
|
-
|
|
232
|
-
if (
|
|
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
|
+
|
|
293
|
+
let tags = this.renderMessagePreview(previewEvent)
|
|
294
|
+
let attachments = sb.get(previewEvent, 'data.message.attachments') || []
|
|
295
|
+
let quickReplies = sb.find(attachments, (att) => att.type === 'quick_replies')
|
|
296
|
+
quickReplies = sb.get(quickReplies, 'quick_replies') || []
|
|
297
|
+
let imgAtt = sb.find(attachments, (att) => sb.includes(att.mimetype, 'image') && att.url)
|
|
298
|
+
let uri = sb.get(imgAtt, 'url') || ''
|
|
299
|
+
if (
|
|
300
|
+
uri &&
|
|
301
|
+
!uri.startsWith('https://') &&
|
|
302
|
+
!uri.startsWith('http://') &&
|
|
303
|
+
!uri.startsWith('content://') &&
|
|
304
|
+
!uri.startsWith('data:')
|
|
305
|
+
) {
|
|
306
|
+
uri = this.props.store.FileURL + uri
|
|
307
|
+
}
|
|
233
308
|
|
|
234
309
|
return (
|
|
235
|
-
<div class={
|
|
236
|
-
<div class=
|
|
237
|
-
<img
|
|
238
|
-
alt='widget avatar'
|
|
239
|
-
class='widget-preview--avatar'
|
|
240
|
-
src={this.props.store.replaceFileUrl(agent.avatar_url)}
|
|
241
|
-
onError={(ev) => this.onProfileError(ev)}
|
|
242
|
-
onload={(_) => this.onProfileReady()}
|
|
243
|
-
/>
|
|
244
|
-
<div class='widget-preview--content' onClick={(e) => this.onPreviewClick(e)}>
|
|
245
|
-
<div class='widget-preview--title'>{agent.fullname}</div>
|
|
246
|
-
<p class='widget-preview--message'>{tags}</p>
|
|
247
|
-
</div>
|
|
310
|
+
<div class={`widget-preview-new-wrapper ${this.state.previewExtraCls}`}>
|
|
311
|
+
<div class={`widget-preview-x-wrapper ${position}`}>
|
|
248
312
|
<div class='widget-preview--btn-close' onClick={(e) => this.closePreview(e)} />
|
|
249
313
|
</div>
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
314
|
+
<div class={`widget-preview-text-message ${position}`} onClick={(e) => this.onPreviewClick(e)}>
|
|
315
|
+
<div class='widget-preview-text-message--header'>
|
|
316
|
+
<img
|
|
317
|
+
alt='widget avatar'
|
|
318
|
+
class='widget-preview--avatar'
|
|
319
|
+
src={this.props.store.replaceFileUrl(agent.avatar_url)}
|
|
320
|
+
/>
|
|
321
|
+
<div class='widget-preview-text-message--author'>
|
|
322
|
+
<div class='widget-preview-text-message--author-text'>{agent.fullname}</div>
|
|
323
|
+
{accountSetting.is_online && (
|
|
324
|
+
<div class='badge badge--success'>
|
|
325
|
+
<div class='dot dot--success mr-1' />
|
|
326
|
+
{'ONLINE'}
|
|
327
|
+
</div>
|
|
328
|
+
)}
|
|
329
|
+
</div>
|
|
330
|
+
</div>
|
|
331
|
+
<div class='widget-preview-text-message--content'>{tags}</div>
|
|
253
332
|
</div>
|
|
333
|
+
{uri && (
|
|
334
|
+
<div class={`widget-preview-image-wrapper ${position}`}>
|
|
335
|
+
<div class='widget-preview-image-item' onClick={() => this.onPreviewClick()}>
|
|
336
|
+
<img src={uri} />
|
|
337
|
+
</div>
|
|
338
|
+
</div>
|
|
339
|
+
)}
|
|
340
|
+
{sb.size(quickReplies) > 0 && (
|
|
341
|
+
<div class={`widget-preview-quick-reply-wrapper ${position}`}>
|
|
342
|
+
{sb.map(quickReplies, (reply) => {
|
|
343
|
+
if (!(reply.title || '').trim()) return
|
|
344
|
+
return (
|
|
345
|
+
<div
|
|
346
|
+
class='widget-preview-quick-reply-item'
|
|
347
|
+
onClick={() => {
|
|
348
|
+
// copy chooseQuickReply function from Event.js
|
|
349
|
+
this.props.onSelectQuickReply({
|
|
350
|
+
text: reply.title,
|
|
351
|
+
format: 'plaintext',
|
|
352
|
+
conversation_id: sb.convoOfEv(previewEvent),
|
|
353
|
+
attachments: [
|
|
354
|
+
{
|
|
355
|
+
type: 'postback',
|
|
356
|
+
postback: {
|
|
357
|
+
event_id: previewEvent.id,
|
|
358
|
+
payload: reply.payload,
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
})
|
|
363
|
+
}}
|
|
364
|
+
>
|
|
365
|
+
{reply.title}
|
|
366
|
+
</div>
|
|
367
|
+
)
|
|
368
|
+
})}
|
|
369
|
+
</div>
|
|
370
|
+
)}
|
|
254
371
|
</div>
|
|
255
372
|
)
|
|
256
373
|
}
|
|
257
374
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
|
262
382
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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()
|
|
266
394
|
}
|
|
267
395
|
|
|
268
396
|
renderButton() {
|
|
@@ -372,19 +500,13 @@ export default class ChatButton extends Com {
|
|
|
372
500
|
|
|
373
501
|
`
|
|
374
502
|
|
|
503
|
+
if (!this.state.ready) cls += ' hidden'
|
|
504
|
+
|
|
375
505
|
return (
|
|
376
506
|
<div class={cls} onClick={(e) => this.onClick(e)}>
|
|
377
507
|
<div class={whitebgcls} style={whiteBgStyle}></div>
|
|
378
508
|
<div class='chat-button--img-container' style={imgcontainerstyle}>
|
|
379
|
-
<img
|
|
380
|
-
width='70'
|
|
381
|
-
height='70'
|
|
382
|
-
alt='chat button'
|
|
383
|
-
class='chat-button--img'
|
|
384
|
-
onload={() => this.onButtonReady()}
|
|
385
|
-
src={imgsrc}
|
|
386
|
-
onError={(e, a) => this.onChatButtonError(e, a)}
|
|
387
|
-
/>
|
|
509
|
+
<img width='70' height='70' alt='chat button' class='chat-button--img' src={imgsrc} />
|
|
388
510
|
</div>
|
|
389
511
|
{this.renderUnread()}
|
|
390
512
|
</div>
|
|
@@ -440,9 +562,7 @@ export default class ChatButton extends Com {
|
|
|
440
562
|
e.preventDefault()
|
|
441
563
|
e.stopPropagation()
|
|
442
564
|
}
|
|
443
|
-
this.
|
|
444
|
-
this.props.store.closePreview()
|
|
445
|
-
this.forceUpdate()
|
|
565
|
+
this.HideGreeting()
|
|
446
566
|
}
|
|
447
567
|
}
|
|
448
568
|
|
package/src/chatbox/Widget.js
CHANGED
|
@@ -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
|
|
|
@@ -63,7 +64,6 @@ export default class Widget extends Com {
|
|
|
63
64
|
if (prevProp.cid !== this.props.cid) {
|
|
64
65
|
this.closeOrder()
|
|
65
66
|
this.setState({clickedJoin: false, quickReplyMessage: {}})
|
|
66
|
-
// this.props.store.setLastview('chat', { cid: this.props.cid })
|
|
67
67
|
sb.setTimeout(() => {
|
|
68
68
|
// focus Events then focus MessageInput
|
|
69
69
|
// if there is any pending form, MessageInput will be disabled
|
|
@@ -132,8 +132,10 @@ export default class Widget extends Com {
|
|
|
132
132
|
else $body = this.renderChat()
|
|
133
133
|
|
|
134
134
|
let position = sb.get(accountSetting, 'desktop_button.position') || 'right'
|
|
135
|
-
if (this.props.store.isMobile()
|
|
135
|
+
if (this.props.store.isMobile() || this.props.store.isEmbededChatMode())
|
|
136
|
+
position = sb.get(accountSetting, 'mobile_button.position', position)
|
|
136
137
|
let cls = 'widget-container widget-container--' + position
|
|
138
|
+
if (this.props.store.isEmbededChatMode()) cls += ' embed-chat'
|
|
137
139
|
if (!this.props.store.isMobile() && sb.get(accountSetting, 'window_mode') === 'full')
|
|
138
140
|
cls += ' widget-container--full'
|
|
139
141
|
if (!this.props.isShow) cls += ' widget-container--hide'
|
package/src/chatbox/main.js
CHANGED
|
@@ -45,9 +45,6 @@ export default class Main extends Com {
|
|
|
45
45
|
|
|
46
46
|
this.setState({
|
|
47
47
|
cssReady: false,
|
|
48
|
-
isShowWidget: false,
|
|
49
|
-
widgetView: '',
|
|
50
|
-
widgetConvoId: '',
|
|
51
48
|
})
|
|
52
49
|
|
|
53
50
|
this.checkExpand()
|
|
@@ -62,16 +59,6 @@ export default class Main extends Com {
|
|
|
62
59
|
})
|
|
63
60
|
this.refreshCSS()
|
|
64
61
|
this.setState({cssReady: true})
|
|
65
|
-
|
|
66
|
-
if (this.props.store.matchIsOpen() && this.props.store.matchLastview().view) {
|
|
67
|
-
if (this.props.store.isMobile()) return // dont auto expand widget on mobile
|
|
68
|
-
this.showWidget(
|
|
69
|
-
Object.assign({}, this.props.store.matchLastview().opts, {view: this.props.store.matchLastview().view}),
|
|
70
|
-
)
|
|
71
|
-
} else {
|
|
72
|
-
restoreViewport()
|
|
73
|
-
if (!this.state.isShowWidget) this.hideWidget()
|
|
74
|
-
}
|
|
75
62
|
}
|
|
76
63
|
|
|
77
64
|
render() {
|
|
@@ -88,23 +75,29 @@ export default class Main extends Com {
|
|
|
88
75
|
return null
|
|
89
76
|
}
|
|
90
77
|
if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_main = sb.Date.now()
|
|
78
|
+
let lastview = this.props.store.matchLastview() || {}
|
|
79
|
+
let isShowWidget = lastview.screen === 'widget'
|
|
80
|
+
let widgetView = lastview.view
|
|
81
|
+
let widgetConvoId = sb.get(lastview, 'opts.cid')
|
|
82
|
+
|
|
91
83
|
return (
|
|
92
|
-
<div class={this.props.store.isMobile() ? 'mobile' : 'desktop'}>
|
|
84
|
+
<div class={this.props.store.isMobile() || this.props.store.isEmbededChatMode() ? 'mobile' : 'desktop'}>
|
|
93
85
|
<ChatButton
|
|
94
86
|
plugin={this.props.plugin}
|
|
95
87
|
store={this.props.store}
|
|
96
88
|
key='chat_button'
|
|
97
89
|
ref={this.refButton}
|
|
98
|
-
isShow={!
|
|
90
|
+
isShow={!isShowWidget}
|
|
99
91
|
onClick={(e) => this.showWidget(e)}
|
|
92
|
+
onSelectQuickReply={(msg) => this.onSelectQuickReply(msg)}
|
|
100
93
|
t={this.props.t}
|
|
101
94
|
/>
|
|
102
95
|
<Widget
|
|
103
96
|
plugin={this.props.plugin}
|
|
104
97
|
store={this.props.store}
|
|
105
|
-
view={
|
|
106
|
-
cid={
|
|
107
|
-
isShow={
|
|
98
|
+
view={widgetView}
|
|
99
|
+
cid={widgetConvoId}
|
|
100
|
+
isShow={isShowWidget}
|
|
108
101
|
onClose={(a) => this.onWidgetClose(a)}
|
|
109
102
|
onGo={(a) => this.showWidget(a)}
|
|
110
103
|
t={this.props.t}
|
|
@@ -124,7 +117,8 @@ export default class Main extends Com {
|
|
|
124
117
|
if (!$widget) return
|
|
125
118
|
if ($widget.wasFormInputed) return
|
|
126
119
|
if (ev.type !== 'message_sent') return
|
|
127
|
-
|
|
120
|
+
let isShowWidget = sb.get(this.props.store.matchLastview(), 'screen') === 'widget'
|
|
121
|
+
if (!isShowWidget) return
|
|
128
122
|
|
|
129
123
|
let byType = sb.get(ev, 'by.type')
|
|
130
124
|
let byid = sb.get(ev, 'by.id') || ''
|
|
@@ -140,50 +134,39 @@ export default class Main extends Com {
|
|
|
140
134
|
if (this.props.store.isMobile()) return
|
|
141
135
|
|
|
142
136
|
if (this.props.plugin._no_auto_expand) return
|
|
143
|
-
|
|
144
|
-
if (this.props.store.matchHasManuallyClosed()) return
|
|
137
|
+
return
|
|
145
138
|
|
|
146
139
|
let convoM = this.props.store.matchConvo('*')
|
|
147
140
|
let redconvo = sb.find(convoM, (convo) => !sb.isConvoSeen(convo, this.props.store.matchUser().id))
|
|
148
141
|
if (!redconvo || !redconvo.id) return
|
|
149
|
-
|
|
142
|
+
let isShowWidget = sb.get(this.props.store.matchLastview(), 'screen') === 'widget'
|
|
143
|
+
if (!isShowWidget) this.showWidget({view: 'chat', cid: redconvo.id})
|
|
150
144
|
}
|
|
151
145
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
146
|
+
onSelectQuickReply(message) {
|
|
147
|
+
this.showWidget({view: 'chat', cid: message.conversation_id})
|
|
148
|
+
this.forceUpdate(() => {
|
|
149
|
+
this.refWidget.current && this.refWidget.current.sendMessage(message)
|
|
150
|
+
})
|
|
158
151
|
}
|
|
159
152
|
|
|
160
153
|
async showWidget(p) {
|
|
161
|
-
this.refButton.current && this.refButton.current.ClearPreview()
|
|
162
|
-
if (!p.view) {
|
|
163
|
-
let lastview = this.props.store.matchLastview() || {}
|
|
164
|
-
p.view = sb.get(lastview, 'view')
|
|
165
|
-
p.cid = sb.get(lastview, 'opts.cid')
|
|
166
|
-
}
|
|
167
|
-
p = p || {}
|
|
154
|
+
//this.refButton.current && this.refButton.current.ClearPreview()
|
|
168
155
|
|
|
156
|
+
let cid = p.cid
|
|
157
|
+
let newView = {screen: 'widget', minimized: 0, view: p.view, previewEvent: {}, opts: {cid}}
|
|
169
158
|
if (!p.view && !p.cid) {
|
|
170
159
|
let convoM = this.props.store.matchConvo('*')
|
|
171
160
|
let redconvo = sb.find(convoM, (convo) => !sb.isConvoSeen(convo, this.props.store.matchUser().id))
|
|
172
161
|
// try to show first convo
|
|
173
|
-
|
|
174
|
-
|
|
162
|
+
cid = sb.get(redconvo, 'id', sb.get(convoM, '0.id'))
|
|
163
|
+
newView.view = 'chat'
|
|
164
|
+
newView.opts = {cid}
|
|
175
165
|
}
|
|
176
166
|
|
|
177
167
|
if (this.props.store.isMobile()) modifyViewport()
|
|
178
|
-
this.
|
|
179
|
-
this.props.store.setIsOpen(true)
|
|
180
|
-
|
|
181
|
-
// lazy load widget
|
|
182
|
-
// if (!Widget) Widget = (await loadWidget()).default
|
|
183
|
-
|
|
168
|
+
this.props.store.updateLastview(newView)
|
|
184
169
|
this.forceUpdate()
|
|
185
|
-
this.setState({isShowWidget: true})
|
|
186
|
-
this.props.store.setLastview(p.view, {cid: p.cid})
|
|
187
170
|
}
|
|
188
171
|
|
|
189
172
|
applyMessage(text) {
|
|
@@ -204,17 +187,12 @@ export default class Main extends Com {
|
|
|
204
187
|
|
|
205
188
|
hideWidget() {
|
|
206
189
|
restoreViewport()
|
|
207
|
-
this.props.store.
|
|
208
|
-
this.
|
|
190
|
+
this.props.store.updateLastview({screen: 'button', previewEvent: {}})
|
|
191
|
+
this.forceUpdate()
|
|
209
192
|
}
|
|
210
193
|
|
|
211
194
|
onWidgetClose() {
|
|
212
|
-
this.refButton.current && this.refButton.current.ClearPreview()
|
|
213
|
-
// need call closePreview if not this will display default agent avatar and account name
|
|
214
|
-
this.refButton.current && this.refButton.current.ClosePreview()
|
|
215
|
-
this.props.store.setHasManuallyClosed()
|
|
216
195
|
this.hideWidget()
|
|
217
|
-
|
|
218
196
|
// emit event close widget
|
|
219
197
|
this.props.store.emitCloseWidgetEvent()
|
|
220
198
|
}
|
package/src/store/store.js
CHANGED
|
@@ -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,17 +483,10 @@ export default class Store {
|
|
|
462
483
|
|
|
463
484
|
// last widget screen
|
|
464
485
|
matchLastview = () => {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
// make sure last view of correct user
|
|
468
|
-
let user = this.cache.match('user') || {}
|
|
469
|
-
if (!user.id) return {}
|
|
470
|
-
if (lastView.user_id != user.id) return {}
|
|
471
|
-
return lastView
|
|
486
|
+
return this.kv.match('lastview') || {}
|
|
472
487
|
}
|
|
473
488
|
|
|
474
489
|
matchIsOpen = () => !!this.kv.match('isopen') // is widget currently open
|
|
475
|
-
matchHasManuallyClosed = () => !!this.kv.match('hasManuallyClosed') // true if user has ever closed the widget
|
|
476
490
|
matchClosePreviewAt = () => this.kv.match('close_preview_at') || 0
|
|
477
491
|
|
|
478
492
|
checkFormToken = (accid, token) => this.api.checkFormToken(accid, token)
|
|
@@ -563,6 +577,28 @@ export default class Store {
|
|
|
563
577
|
)
|
|
564
578
|
}
|
|
565
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
|
+
|
|
566
602
|
async _initResource(accid, auth, realtimep) {
|
|
567
603
|
this.g_sync = {}
|
|
568
604
|
|
|
@@ -591,6 +627,7 @@ export default class Store {
|
|
|
591
627
|
this.seenLoop()
|
|
592
628
|
if (typeof sbz_info != 'undefined') sbz_info.store_9 = true
|
|
593
629
|
await this.reconnect({user: user}) // already fetched
|
|
630
|
+
this.standardlizeLastview()
|
|
594
631
|
if (typeof sbz_info != 'undefined') sbz_info.store_10 = true
|
|
595
632
|
this.readyGate.open()
|
|
596
633
|
this.reconnectWs(accid, user.id)
|
|
@@ -1212,20 +1249,21 @@ export default class Store {
|
|
|
1212
1249
|
onResetCSS = (o, cb) => this.pubsub.on2(o, 'resetCSS', cb)
|
|
1213
1250
|
onHighlight = (o, cb) => this.pubsub.on2(o, 'highlight', cb)
|
|
1214
1251
|
|
|
1215
|
-
setHasManuallyClosed = () => this.kv.put('hasManuallyClosed', true)
|
|
1216
|
-
setIsOpen = (isopen) => {
|
|
1217
|
-
let lastisopen = this.kv.match('isopen')
|
|
1218
|
-
this.kv.put('isopen', isopen)
|
|
1219
|
-
if (!lastisopen && isopen) {
|
|
1220
|
-
sendEventToThirdParty('SUBIZ Chat', 'Opened', 'Subiz Windows')
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
1252
|
closePreview = () => this.kv.put('close_preview_at', new sb.Date().getTime())
|
|
1224
|
-
|
|
1253
|
+
updateLastview = (obj) => {
|
|
1225
1254
|
let user = this.cache.match('user') || {}
|
|
1226
1255
|
if (!user.id) return // store not init
|
|
1227
|
-
|
|
1256
|
+
let lastview = this.matchLastview() || {}
|
|
1257
|
+
let newview = {
|
|
1258
|
+
...lastview,
|
|
1259
|
+
...obj,
|
|
1260
|
+
user_id: user.id,
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
this.kv.put('lastview', newview)
|
|
1264
|
+
this.pubsub.publish('lastview', newview, lastview)
|
|
1228
1265
|
}
|
|
1266
|
+
onLastview = (o, cb) => this.pubsub.on2(o, 'lastview', cb)
|
|
1229
1267
|
|
|
1230
1268
|
matchLastPluginRun(pluginid) {
|
|
1231
1269
|
let log = this.kv.match('plugin_run_logs') || {}
|