@subiz/widget-v4 4.1.116 → 4.1.119
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 +1 -0
- package/assets/less/chatbox.less +2 -0
- package/assets/less/message.less +42 -22
- package/assets/less/message_input.less +2 -0
- package/assets/less/order.less +1 -1
- package/assets/less/widget.less +33 -16
- package/assets/less/widget_header.less +35 -36
- package/compiled_src/chatbox/AgentsAvatar.js +1 -1
- package/compiled_src/chatbox/Event.js +70 -15
- package/compiled_src/chatbox/Events.js +108 -19
- package/compiled_src/chatbox/Header.js +5 -4
- package/compiled_src/chatbox/InfoMessage.js +2 -13
- package/compiled_src/chatbox/MessageInput.js +25 -9
- package/compiled_src/chatbox/TextMessage.js +11 -2
- package/compiled_src/chatbox/Widget.js +29 -22
- package/compiled_src/chatbox/main.js +3 -0
- package/compiled_src/chatbox/time.js +1 -0
- package/compiled_src/lib.js +4 -0
- package/compiled_src/plugin.js +4 -0
- package/compiled_src/util/common.js +89 -0
- package/dist/185.js +19 -19
- package/dist/19641cfa41e.278.js +1 -0
- package/dist/19641cfa41e.app.js +1 -0
- package/dist/{195ec5442e3.index.html → 19641cfa41e.index.html} +1 -1
- package/dist/{195ec5442e3.library.html → 19641cfa41e.library.html} +1 -1
- package/dist/19641cfa41e.library.js +1 -0
- package/dist/{195ec5442e3.preview.html → 19641cfa41e.preview.html} +1 -1
- package/dist/19641cfa41e.preview.js +1 -0
- package/dist/19641cfa41e.webview.js +1 -0
- package/dist/278.js +1 -1
- package/dist/HASH +1 -1
- package/dist/screenshoot.js +562 -185
- package/package.json +4 -4
- package/src/chatbox/AgentsAvatar.js +1 -1
- package/src/chatbox/Event.js +76 -15
- package/src/chatbox/Events.js +95 -14
- package/src/chatbox/Header.js +3 -2
- package/src/chatbox/InfoMessage.js +0 -14
- package/src/chatbox/MessageInput.js +23 -7
- package/src/chatbox/TextMessage.js +13 -0
- package/src/chatbox/Widget.js +22 -19
- package/src/chatbox/main.js +4 -0
- package/src/chatbox/time.js +12 -8
- package/src/lib.js +5 -0
- package/src/plugin.js +5 -0
- package/src/util/common.js +121 -0
- package/up +33 -21
- package/compiled_src/chatbox/Typing.js +0 -77
- package/dist/195ec5442e3.278.js +0 -1
- package/dist/195ec5442e3.app.js +0 -1
- package/dist/195ec5442e3.library.js +0 -1
- package/dist/195ec5442e3.preview.js +0 -1
- package/dist/195ec5442e3.webview.js +0 -1
- package/src/chatbox/Typing.js +0 -72
- /package/dist/{195ec5442e3.127.js → 19641cfa41e.127.js} +0 -0
- /package/dist/{195ec5442e3.132.js → 19641cfa41e.132.js} +0 -0
- /package/dist/{195ec5442e3.185.js → 19641cfa41e.185.js} +0 -0
- /package/dist/{195ec5442e3.27.js → 19641cfa41e.27.js} +0 -0
- /package/dist/{195ec5442e3.459.js → 19641cfa41e.459.js} +0 -0
- /package/dist/{195ec5442e3.490.js → 19641cfa41e.490.js} +0 -0
- /package/dist/{195ec5442e3.74.js → 19641cfa41e.74.js} +0 -0
- /package/dist/{195ec5442e3.997.js → 19641cfa41e.997.js} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subiz/widget-v4",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.119",
|
|
4
4
|
"main": "./compiled_src/lib.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "npx webpack serve --config webpack.dev.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"core-js": "^3.41.0",
|
|
18
18
|
"css-loader": "5.2.7",
|
|
19
19
|
"file-loader": "^6.2.0",
|
|
20
|
-
"less": "^4.
|
|
20
|
+
"less": "^4.3.0",
|
|
21
21
|
"less-loader": "^12.2.0",
|
|
22
22
|
"preact": "10.19.3"
|
|
23
23
|
},
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"babel-loader": "^10.0.0",
|
|
31
31
|
"babel-plugin-syntax-jsx": "^6.18.0",
|
|
32
32
|
"html-webpack-plugin": "^5.6.3",
|
|
33
|
-
"puppeteer": "^24.6.
|
|
34
|
-
"webpack": "^5.99.
|
|
33
|
+
"puppeteer": "^24.6.1",
|
|
34
|
+
"webpack": "^5.99.5",
|
|
35
35
|
"webpack-bundle-analyzer": "^4.10.2",
|
|
36
36
|
"webpack-cli": "^6.0.1",
|
|
37
37
|
"webpack-dev-server": "^5.2.1"
|
|
@@ -38,7 +38,7 @@ export default function AgentsAvatar(props) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
agents = sb.filter(agents, (ag) => !!ag)
|
|
41
|
-
if (agents.length === 0) {
|
|
41
|
+
if (agents.length === 0 || props.agent_ids === undefined || sb.size(props.agent_ids) === 0) {
|
|
42
42
|
// use account avatar
|
|
43
43
|
return (
|
|
44
44
|
<div class={`group-avatar group-avatar--${mode}`}>
|
package/src/chatbox/Event.js
CHANGED
|
@@ -33,10 +33,13 @@ export default class Event extends Com {
|
|
|
33
33
|
render() {
|
|
34
34
|
var ev = sb.get(this.props.event, 'ev', {})
|
|
35
35
|
switch (ev.type) {
|
|
36
|
+
case 'conversation_typing':
|
|
37
|
+
return this.renderTyping()
|
|
36
38
|
case 'conversation_joined':
|
|
37
39
|
// return this.renderMessageChatJoin()
|
|
38
40
|
break
|
|
39
41
|
case 'message_sent':
|
|
42
|
+
if (this.props.event.is_typing) return this.renderTyping()
|
|
40
43
|
return this.renderMessageSent()
|
|
41
44
|
case 'conversation_state_updated':
|
|
42
45
|
case 'conversation_rating_requested':
|
|
@@ -149,19 +152,74 @@ export default class Event extends Com {
|
|
|
149
152
|
})
|
|
150
153
|
}
|
|
151
154
|
|
|
155
|
+
renderTyping() {
|
|
156
|
+
let innercls = 'agent-convo-event-inner'
|
|
157
|
+
var html = `
|
|
158
|
+
<html>
|
|
159
|
+
<head>
|
|
160
|
+
<style>
|
|
161
|
+
.typing-container {
|
|
162
|
+
width: 100vw;
|
|
163
|
+
height: 100vh;
|
|
164
|
+
display: flex;
|
|
165
|
+
align-items: center;
|
|
166
|
+
gap: 4px;
|
|
167
|
+
justify-content: center;
|
|
168
|
+
}
|
|
169
|
+
.typing-dot {
|
|
170
|
+
display: inline-block;
|
|
171
|
+
vertical-align: middle;
|
|
172
|
+
width: 8px;
|
|
173
|
+
height: 8px;
|
|
174
|
+
background: black;
|
|
175
|
+
border-radius: 50%;
|
|
176
|
+
animation: typing 0.5s infinite alternate;
|
|
177
|
+
}
|
|
178
|
+
.typing-dot:nth-of-type(2) {
|
|
179
|
+
animation-delay: 0.2s;
|
|
180
|
+
}
|
|
181
|
+
.typing-dot:nth-of-type(3) {
|
|
182
|
+
animation-delay: 0.6s;
|
|
183
|
+
}
|
|
184
|
+
@keyframes typing {
|
|
185
|
+
0% {
|
|
186
|
+
opacity: 0.9;
|
|
187
|
+
}
|
|
188
|
+
100% {
|
|
189
|
+
opacity: 0.4;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
</style>
|
|
193
|
+
</head>
|
|
194
|
+
<body style="padding: 0; margin: 0">
|
|
195
|
+
<div class="typing-container">
|
|
196
|
+
<span class="typing-dot"></span>
|
|
197
|
+
<span class="typing-dot"></span>
|
|
198
|
+
<span class="typing-dot"></span>
|
|
199
|
+
</div>
|
|
200
|
+
</body>
|
|
201
|
+
</html>
|
|
202
|
+
`
|
|
203
|
+
let src = 'data:text/html,' + encodeURIComponent(html)
|
|
204
|
+
return (
|
|
205
|
+
<div class='convo-event agent-message'>
|
|
206
|
+
<div class='agent-convo-event-wrapper'>
|
|
207
|
+
<div class={innercls}>
|
|
208
|
+
<div class='message-agent message-text--agent' style='opacity: 0.6 !important'>
|
|
209
|
+
<iframe
|
|
210
|
+
src={src}
|
|
211
|
+
style='width: 35px !important; height: 20px !important; display: block !important; overflow: hidden !important; padding: 0 !important '
|
|
212
|
+
></iframe>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
152
220
|
renderMessageSent() {
|
|
153
221
|
let ev = this.props.event.ev
|
|
154
222
|
this.tryLoadOrder(ev)
|
|
155
|
-
var $time = null
|
|
156
|
-
if (this.props.event.show_time) {
|
|
157
|
-
$time = (
|
|
158
|
-
<div class='convo-event-time'>
|
|
159
|
-
<Time time={ev.created} t={this.props.t} />
|
|
160
|
-
</div>
|
|
161
|
-
)
|
|
162
|
-
}
|
|
163
|
-
if (this.props.store.isAIDevMode()) $time = null
|
|
164
|
-
|
|
165
223
|
let t = new sb.Date(ev.created).toLocaleString()
|
|
166
224
|
// message of agent
|
|
167
225
|
if (sb.get(ev, 'by.type') !== 'user') {
|
|
@@ -171,11 +229,16 @@ export default class Event extends Com {
|
|
|
171
229
|
if (this.props.isLast) innercls += ' last'
|
|
172
230
|
return (
|
|
173
231
|
<div class='convo-event agent-message'>
|
|
174
|
-
{$time}
|
|
175
232
|
{$sender}
|
|
176
233
|
<div class='agent-convo-event-wrapper'>
|
|
177
234
|
<div class={innercls}>
|
|
178
|
-
<TextMessage
|
|
235
|
+
<TextMessage
|
|
236
|
+
showTime={this.props.event.show_time}
|
|
237
|
+
isLast={this.props.isLast}
|
|
238
|
+
store={this.props.store}
|
|
239
|
+
ev={ev}
|
|
240
|
+
onLink={this.props.onLink}
|
|
241
|
+
/>
|
|
179
242
|
<ImageAttachments store={this.props.store} ev={ev} />
|
|
180
243
|
<AudioAttachments store={this.props.store} ev={ev} />
|
|
181
244
|
<VideoAttachments store={this.props.store} ev={ev} />
|
|
@@ -223,7 +286,7 @@ export default class Event extends Com {
|
|
|
223
286
|
}
|
|
224
287
|
|
|
225
288
|
let $sender = null
|
|
226
|
-
if (this.props.event.mode === 'lead') $sender = <div class='pt-3'></div>
|
|
289
|
+
// if (this.props.event.mode === 'lead') $sender = <div class='pt-3'></div>
|
|
227
290
|
|
|
228
291
|
let $error = null
|
|
229
292
|
if (ev._error && ev.type === 'message_sent') {
|
|
@@ -239,7 +302,6 @@ export default class Event extends Com {
|
|
|
239
302
|
|
|
240
303
|
return (
|
|
241
304
|
<div class='convo-event user-message'>
|
|
242
|
-
{$time}
|
|
243
305
|
{$sender}
|
|
244
306
|
<div class='message-user__container'>
|
|
245
307
|
{$dot}
|
|
@@ -307,7 +369,6 @@ export default class Event extends Com {
|
|
|
307
369
|
|
|
308
370
|
renderReactions() {
|
|
309
371
|
if (this.props.store.isAIDevMode()) return null
|
|
310
|
-
|
|
311
372
|
let ev = sb.get(this.props.event, 'ev') || {}
|
|
312
373
|
let pongs = sb.get(ev, 'data.message.pongs') || []
|
|
313
374
|
let hasLike = this.hasLike()
|
package/src/chatbox/Events.js
CHANGED
|
@@ -29,10 +29,66 @@ export default class Events extends Com {
|
|
|
29
29
|
this.checkAndSeen()
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
componentDidMount() {
|
|
33
|
+
this.setState({
|
|
34
|
+
isShowTyping: false,
|
|
35
|
+
typing_event: {},
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
this.props.store.onConvoEvent(this, (ev) => {
|
|
39
|
+
if (sb.convoOfEv(ev) !== this.props.cid) return
|
|
40
|
+
// if (sb.get(ev, 'by.id') === user.id) return
|
|
41
|
+
// fixwidget in dashboard show typing of user
|
|
42
|
+
if (sb.get(ev, 'by.type') === 'user') return
|
|
43
|
+
|
|
44
|
+
let oldby = sb.get(this.state.typing_event, 'by.id')
|
|
45
|
+
if (oldby && sb.get(ev, 'by.id') !== oldby) return
|
|
46
|
+
|
|
47
|
+
if (sb.get(ev, 'type') === 'message_sent') {
|
|
48
|
+
// stop the typing
|
|
49
|
+
if (this.timer) sb.clearTimeout(this.timer)
|
|
50
|
+
this.timer = null
|
|
51
|
+
this.setState({isShowTyping: false})
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
if (sb.get(ev, 'type') !== 'conversation_typing') return
|
|
55
|
+
|
|
56
|
+
// dont show typing of agent, some agent dont like this
|
|
57
|
+
let ag = this.props.store.matchAgent(sb.get(ev, 'by.id')) || {}
|
|
58
|
+
if (ag.type == 'agent' && !sb.get(this.props.plugin, 'chatbox.show_agent_typing')) return
|
|
59
|
+
this.setState({typing_event: ev, isShowTyping: true})
|
|
60
|
+
if (this.timer) sb.clearTimeout(this.timer)
|
|
61
|
+
this.timer = sb.setTimeout(() => {
|
|
62
|
+
if (sb.convoOfEv(ev) !== this.props.cid) return
|
|
63
|
+
this.timer = null
|
|
64
|
+
this.setState({isShowTyping: false})
|
|
65
|
+
}, 5000)
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
32
69
|
componentDidUpdate(prevProps) {
|
|
33
70
|
if (prevProps.cid !== this.props.cid) this.loadConvo()
|
|
34
71
|
}
|
|
35
72
|
|
|
73
|
+
ShowTyping() {
|
|
74
|
+
this.setState({
|
|
75
|
+
isShowTyping: true,
|
|
76
|
+
typing_event: {
|
|
77
|
+
id: 'evzz' + sb.Date.now(),
|
|
78
|
+
created: sb.Date.now(),
|
|
79
|
+
by: {
|
|
80
|
+
type: 'agent',
|
|
81
|
+
},
|
|
82
|
+
type: 'conversation_typing',
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
if (this.timer) sb.clearTimeout(this.timer)
|
|
86
|
+
this.timer = sb.setTimeout(() => {
|
|
87
|
+
this.timer = null
|
|
88
|
+
this.setState({isShowTyping: false})
|
|
89
|
+
}, 5000)
|
|
90
|
+
}
|
|
91
|
+
|
|
36
92
|
render() {
|
|
37
93
|
if (this.state.error) return this.renderError()
|
|
38
94
|
let events = sb.map(this.props.store.listEvents(this.props.cid))
|
|
@@ -53,20 +109,29 @@ export default class Events extends Com {
|
|
|
53
109
|
|
|
54
110
|
let convo = this.props.store.matchConvo(this.props.cid)
|
|
55
111
|
events = sb.map(events, (ev) => ({ev: ev}))
|
|
56
|
-
processEvents(convo, events)
|
|
57
112
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
let ev = sb.
|
|
61
|
-
let
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
113
|
+
// console.log('-----------', this.state.isShowTyping, this.state.typing_event)
|
|
114
|
+
if (this.state.isShowTyping) {
|
|
115
|
+
let ev = this.state.typing_event || {id: 'evzz' + sb.Date.now(), created: sb.Date.now(), by: {type: 'agent'}}
|
|
116
|
+
let fakeev = {
|
|
117
|
+
is_typing: true,
|
|
118
|
+
id: ev.id,
|
|
119
|
+
ev: {
|
|
120
|
+
id: ev.id,
|
|
121
|
+
created: ev.created,
|
|
122
|
+
by: ev.by,
|
|
123
|
+
type: 'message_sent',
|
|
124
|
+
data: {message: {text: '...', conversation_id: this.props.cid}},
|
|
125
|
+
},
|
|
65
126
|
}
|
|
127
|
+
console.log('FA', fakeev)
|
|
128
|
+
events.push(fakeev)
|
|
66
129
|
}
|
|
67
130
|
|
|
131
|
+
processEvents(convo, events)
|
|
132
|
+
|
|
68
133
|
let $events = sb.map(events, (ev) => {
|
|
69
|
-
let isLast = ev.ev.id ===
|
|
134
|
+
let isLast = ev.ev.id === sb.get(convo, 'last_message_sent.id')
|
|
70
135
|
return (
|
|
71
136
|
<Event
|
|
72
137
|
isLast={isLast}
|
|
@@ -85,11 +150,18 @@ export default class Events extends Com {
|
|
|
85
150
|
|
|
86
151
|
let $loading = null
|
|
87
152
|
let style = 'opacity: 1 !important'
|
|
88
|
-
if (this.
|
|
153
|
+
if (this.props.creating) {
|
|
89
154
|
$loading = <Spinner static mode={sb.get(this.props.chatbox, 'primary_color', 'dark')} size='120' center />
|
|
90
155
|
style = 'opacity: 0 !important'
|
|
91
156
|
}
|
|
92
157
|
|
|
158
|
+
if (this.state.loading) {
|
|
159
|
+
if (sb.Date.now() - this.state.loading > 500) {
|
|
160
|
+
$loading = <Spinner static mode={sb.get(this.props.chatbox, 'primary_color', 'dark')} size='120' center />
|
|
161
|
+
style = 'opacity: 0 !important'
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
93
165
|
return (
|
|
94
166
|
<Fragment>
|
|
95
167
|
{$loading}
|
|
@@ -171,9 +243,13 @@ export default class Events extends Com {
|
|
|
171
243
|
if (!this.props.cid) return
|
|
172
244
|
// load msg
|
|
173
245
|
this.lastContentOffsetY = 0
|
|
174
|
-
this.setState({loading:
|
|
246
|
+
this.setState({loading: false})
|
|
175
247
|
let events = this.props.store.listEvents(this.props.cid)
|
|
176
248
|
if (sb.size(events) === 0) {
|
|
249
|
+
this.setState({loading: sb.Date.now()})
|
|
250
|
+
sb.setTimeout(() => {
|
|
251
|
+
this.forceUpdate()
|
|
252
|
+
}, 800)
|
|
177
253
|
let cid = this.props.cid
|
|
178
254
|
|
|
179
255
|
let {error} = await this.props.store.fetchMoreEvents(cid)
|
|
@@ -184,11 +260,10 @@ export default class Events extends Com {
|
|
|
184
260
|
return
|
|
185
261
|
}
|
|
186
262
|
}
|
|
187
|
-
this.setState({loading: true})
|
|
188
263
|
this.props.store.fetchMoreEvents(this.props.cid)
|
|
189
264
|
this.setState({error: false})
|
|
190
265
|
this.scrollToBottom()
|
|
191
|
-
sb.setTimeout(() => this.setState({loading: false}), 50)
|
|
266
|
+
// sb.setTimeout(() => this.setState({loading: false}), 50)
|
|
192
267
|
}
|
|
193
268
|
|
|
194
269
|
isBottom() {
|
|
@@ -205,7 +280,7 @@ export default class Events extends Com {
|
|
|
205
280
|
sb.setTimeout(() => {
|
|
206
281
|
const $div = this.refBody
|
|
207
282
|
if ($div) $div.scrollTop = $div.scrollHeight
|
|
208
|
-
},
|
|
283
|
+
}, 100)
|
|
209
284
|
|
|
210
285
|
if (this.props.isShow) {
|
|
211
286
|
if (this.props.store.browserVisibility === 'visible' && document.hasFocus()) {
|
|
@@ -224,9 +299,13 @@ function processEvents(convo, events) {
|
|
|
224
299
|
|
|
225
300
|
// show time for the first msg sent
|
|
226
301
|
// insert time
|
|
302
|
+
var lastAgentEvent
|
|
227
303
|
for (var i = 1; i < events.length; i++) {
|
|
228
304
|
let curEvent = events[i]
|
|
229
305
|
let lastEvent = events[i - 1]
|
|
306
|
+
if (sb.get(curEvent, 'ev.by.type') != 'user' && !curEvent.is_typing) {
|
|
307
|
+
lastAgentEvent = curEvent
|
|
308
|
+
}
|
|
230
309
|
|
|
231
310
|
if (visibleEvent(curEvent.ev)) {
|
|
232
311
|
let elapsedSec = sb.unixSec(curEvent.ev.created) - sb.unixSec(lastEvent.ev.created)
|
|
@@ -234,6 +313,8 @@ function processEvents(convo, events) {
|
|
|
234
313
|
}
|
|
235
314
|
}
|
|
236
315
|
|
|
316
|
+
if (lastAgentEvent) lastAgentEvent.show_time = true
|
|
317
|
+
|
|
237
318
|
for (var i = 0; i < events.length; i++) {
|
|
238
319
|
let curEvent = events[i]
|
|
239
320
|
if (sb.get(curEvent, 'ev.type') === 'message_sent') {
|
package/src/chatbox/Header.js
CHANGED
|
@@ -54,7 +54,8 @@ export default class Header extends Com {
|
|
|
54
54
|
return (
|
|
55
55
|
<div class={cls} style={style}>
|
|
56
56
|
{$back}
|
|
57
|
-
<
|
|
57
|
+
<div class="mr-2"></div>
|
|
58
|
+
<AgentsAvatar plugin={this.props.plugin} store={this.props.store} mode='secondary' />
|
|
58
59
|
<div class='widget-header--title-container'>
|
|
59
60
|
<div class='widget-header--title'>{this.getTitle()}</div>
|
|
60
61
|
<div class='widget-header--description' title={desc}>
|
|
@@ -201,7 +202,7 @@ Vui lòng hỏi chúng tôi bất cứ điều gì hoặc chia sẻ phản hồi
|
|
|
201
202
|
if (accSetting.hide_close_button) return null
|
|
202
203
|
return (
|
|
203
204
|
<div
|
|
204
|
-
class='widget-header--button
|
|
205
|
+
class='widget-header--button-close'
|
|
205
206
|
data-tooltip={this.props.t('close')}
|
|
206
207
|
data-tooltip-position='bottom'
|
|
207
208
|
onClick={(e) => this.onCloseClick(e)}
|
|
@@ -7,24 +7,12 @@ function getRateLang(rating) {
|
|
|
7
7
|
return 'great'
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
import Time from './time.js'
|
|
11
10
|
import {Com} from '../common.js'
|
|
12
11
|
import {h} from 'preact'
|
|
13
12
|
// [ 'ev'],
|
|
14
13
|
export default class InfoMessage extends Com {
|
|
15
14
|
render() {
|
|
16
15
|
let ev = this.props.ev.ev
|
|
17
|
-
var $time = null
|
|
18
|
-
|
|
19
|
-
if (this.props.ev.show_time) {
|
|
20
|
-
$time = (
|
|
21
|
-
<div class='convo-event-time'>
|
|
22
|
-
<Time time={ev.created} t={this.props.t} />
|
|
23
|
-
</div>
|
|
24
|
-
)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (this.props.store.isAIDevMode()) $time = null
|
|
28
16
|
|
|
29
17
|
// if (this.ev.type === 'conversation_rating_requested') return <div class="info-message"></div>
|
|
30
18
|
if (ev.type === 'conversation_rated') {
|
|
@@ -32,7 +20,6 @@ export default class InfoMessage extends Com {
|
|
|
32
20
|
if (rating.no_rating) return null
|
|
33
21
|
return (
|
|
34
22
|
<div class='convo-event'>
|
|
35
|
-
{$time}
|
|
36
23
|
<div class='info-message'>
|
|
37
24
|
{this.props.t('rated_as') + ' ' + this.props.t(getRateLang(rating.rating)).toLowerCase()}
|
|
38
25
|
</div>
|
|
@@ -42,7 +29,6 @@ export default class InfoMessage extends Com {
|
|
|
42
29
|
if (ev.type === 'conversation_state_updated' && sb.get(ev, 'data.conversation.state') === 'ended') {
|
|
43
30
|
return (
|
|
44
31
|
<div class='convo-event'>
|
|
45
|
-
{$time}
|
|
46
32
|
<div class='info-message'>{this.props.t('conversation_ended')}</div>
|
|
47
33
|
</div>
|
|
48
34
|
)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import sb from '../util/index.js'
|
|
2
2
|
import {Com} from '../common.js'
|
|
3
3
|
import {h, createRef} from 'preact'
|
|
4
|
+
import Spinner from './spinner.js'
|
|
4
5
|
import Emoji from './Emoji.js'
|
|
5
|
-
// props: ['disabled', 'cid'],
|
|
6
|
+
// props: ['disabled', 'cid', 'is_loading'],
|
|
6
7
|
export default class MessageInput extends Com {
|
|
7
8
|
constructor(props) {
|
|
8
9
|
super(props)
|
|
@@ -37,7 +38,7 @@ export default class MessageInput extends Com {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
render() {
|
|
40
|
-
var buttons = (
|
|
41
|
+
var $buttons = (
|
|
41
42
|
<div class='d-flex flex-row align-self-end'>
|
|
42
43
|
{this.renderEmoji()}
|
|
43
44
|
<div
|
|
@@ -49,7 +50,7 @@ export default class MessageInput extends Com {
|
|
|
49
50
|
)
|
|
50
51
|
var msg = sb.trim(this.state.msgValue)
|
|
51
52
|
if (msg.length > 0) {
|
|
52
|
-
buttons = (
|
|
53
|
+
$buttons = (
|
|
53
54
|
<div class='d-flex flex-row align-self-end'>
|
|
54
55
|
{this.renderEmoji()}
|
|
55
56
|
<div
|
|
@@ -61,9 +62,17 @@ export default class MessageInput extends Com {
|
|
|
61
62
|
)
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
if (this.props.is_loading) {
|
|
66
|
+
$buttons = (
|
|
67
|
+
<div class='d-flex flex-row align-self-end'>
|
|
68
|
+
<Spinner size='32' />
|
|
69
|
+
</div>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
64
73
|
var containercls = ''
|
|
65
74
|
var disabled = this.hasUnfinishRequiredFormOrLock() || this.props.disabled
|
|
66
|
-
if (disabled) containercls = 'message-input--disabled'
|
|
75
|
+
if (disabled || this.props.is_loading) containercls = 'message-input--disabled'
|
|
67
76
|
|
|
68
77
|
return (
|
|
69
78
|
<div
|
|
@@ -77,7 +86,7 @@ export default class MessageInput extends Com {
|
|
|
77
86
|
disabled={disabled}
|
|
78
87
|
class='message-input--input'
|
|
79
88
|
maxlength='1024'
|
|
80
|
-
placeholder={this.props.t('message_input_help')}
|
|
89
|
+
placeholder={this.props.t('message_input_help').substr(0, 25)}
|
|
81
90
|
ref={this.refMessageInput}
|
|
82
91
|
rows='1'
|
|
83
92
|
value={this.state.msgValue}
|
|
@@ -86,7 +95,7 @@ export default class MessageInput extends Com {
|
|
|
86
95
|
data-emojiable='true'
|
|
87
96
|
onKeydown={(e) => this.onKeydown(e)}
|
|
88
97
|
/>
|
|
89
|
-
{buttons}
|
|
98
|
+
{$buttons}
|
|
90
99
|
</div>
|
|
91
100
|
)
|
|
92
101
|
}
|
|
@@ -226,6 +235,11 @@ export default class MessageInput extends Com {
|
|
|
226
235
|
)
|
|
227
236
|
}
|
|
228
237
|
|
|
238
|
+
applyMessage(text) {
|
|
239
|
+
this.setState({msgValue: text})
|
|
240
|
+
this.resizeInput()
|
|
241
|
+
}
|
|
242
|
+
|
|
229
243
|
focus() {
|
|
230
244
|
if (this.props.disabled) return
|
|
231
245
|
this.refMessageInput.current && this.refMessageInput.current.focus()
|
|
@@ -319,9 +333,11 @@ export default class MessageInput extends Com {
|
|
|
319
333
|
msg = msg || sb.trim(this.state.msgValue) || ''
|
|
320
334
|
if (!msg) return
|
|
321
335
|
if (this.props.disabled) return
|
|
336
|
+
if (this.props.onSend) {
|
|
337
|
+
await this.props.onSend({text: msg, format: 'plaintext'})
|
|
338
|
+
}
|
|
322
339
|
this.setState({openEmoji: false, msgValue: ''})
|
|
323
340
|
this.resizeInput()
|
|
324
|
-
this.props.onSend && this.props.onSend({text: msg, format: 'plaintext'})
|
|
325
341
|
}
|
|
326
342
|
|
|
327
343
|
sendTyping() {
|
|
@@ -3,8 +3,19 @@ import Block from './block.js'
|
|
|
3
3
|
import {Com} from '../common.js'
|
|
4
4
|
import {h} from 'preact'
|
|
5
5
|
import Emoji from './Emoji.js'
|
|
6
|
+
import Time from './time.js'
|
|
6
7
|
|
|
7
8
|
export default class TextMessage extends Com {
|
|
9
|
+
renderTime() {
|
|
10
|
+
if (!this.props.showTime && !this.props.isLast && !this.props.isFirst) return null
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div>
|
|
14
|
+
<Time class='inline-time' time={sb.get(this.props.ev, 'created', sb.Date.now())} t={this.props.t} />
|
|
15
|
+
</div>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
8
19
|
render() {
|
|
9
20
|
var format = sb.get(this.props.ev, 'data.message.format', 'plaintext')
|
|
10
21
|
let block = sb.get(this.props.ev, 'data.message.block')
|
|
@@ -48,6 +59,7 @@ export default class TextMessage extends Com {
|
|
|
48
59
|
return (
|
|
49
60
|
<div class='message-agent message-text--agent' title={t}>
|
|
50
61
|
{tags}
|
|
62
|
+
{this.renderTime()}
|
|
51
63
|
</div>
|
|
52
64
|
)
|
|
53
65
|
return (
|
|
@@ -66,6 +78,7 @@ export default class TextMessage extends Com {
|
|
|
66
78
|
return (
|
|
67
79
|
<div class='message-agent message-text--agent' title={t}>
|
|
68
80
|
<Block block={block} onLink={this.props.onLink} />
|
|
81
|
+
{this.renderTime()}
|
|
69
82
|
</div>
|
|
70
83
|
)
|
|
71
84
|
}
|
package/src/chatbox/Widget.js
CHANGED
|
@@ -8,7 +8,7 @@ var checkedimg = require('../../assets/img/done_gray.svg')
|
|
|
8
8
|
var empty = require('../../assets/img/empty.svg')
|
|
9
9
|
import MessageInput from './MessageInput.js'
|
|
10
10
|
import Events from './Events.js'
|
|
11
|
-
import Typing from './Typing.js'
|
|
11
|
+
// import Typing from './Typing.js'
|
|
12
12
|
import Rating from './Rating.js'
|
|
13
13
|
// import Order from './Order.js'
|
|
14
14
|
let Order = false
|
|
@@ -17,7 +17,6 @@ import ListField from './ListField.js'
|
|
|
17
17
|
|
|
18
18
|
const defaultAvatar = 'https://vcdn.subiz-cdn.com/file/fiqoahedjbgwclpouoml-avatar_default_baa8a1d7.png'
|
|
19
19
|
|
|
20
|
-
import Spinner from './spinner.js'
|
|
21
20
|
import Time from './time.js'
|
|
22
21
|
import {Com} from '../common.js'
|
|
23
22
|
import {h, createRef} from 'preact'
|
|
@@ -49,6 +48,10 @@ export default class Widget extends Com {
|
|
|
49
48
|
this.updateFormDataFields()
|
|
50
49
|
}
|
|
51
50
|
|
|
51
|
+
applyMessage(text) {
|
|
52
|
+
this.focusInput(text)
|
|
53
|
+
}
|
|
54
|
+
|
|
52
55
|
componentDidUpdate(prevProp) {
|
|
53
56
|
if (prevProp.isShow !== this.props.isShow) {
|
|
54
57
|
if (this.props.isShow && !this.props.store.isMobile()) this.focusInput()
|
|
@@ -64,7 +67,7 @@ export default class Widget extends Com {
|
|
|
64
67
|
// focus Events then focus MessageInput
|
|
65
68
|
// if there is any pending form, MessageInput will be disabled
|
|
66
69
|
// and dont steal focus from Events
|
|
67
|
-
this
|
|
70
|
+
this.$events && this.$events.focus()
|
|
68
71
|
if (!this.props.store.isMobile()) this.focusInput()
|
|
69
72
|
}, 100)
|
|
70
73
|
this.updateFormDataFields()
|
|
@@ -73,7 +76,7 @@ export default class Widget extends Com {
|
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
ShowTyping() {
|
|
76
|
-
this
|
|
79
|
+
this.$events && this.$events.ShowTyping()
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
shouldShowForm() {
|
|
@@ -130,7 +133,7 @@ export default class Widget extends Com {
|
|
|
130
133
|
let position = sb.get(accountSetting, 'desktop_button.position') || 'right'
|
|
131
134
|
if (this.props.store.isMobile()) position = sb.get(accountSetting, 'mobile_button.position', position)
|
|
132
135
|
let cls = 'widget-container widget-container--' + position
|
|
133
|
-
if (
|
|
136
|
+
if (!this.props.store.isMobile() && sb.get(accountSetting, 'window_mode') === 'full')
|
|
134
137
|
cls += ' widget-container--full'
|
|
135
138
|
if (!this.props.isShow) cls += ' widget-container--hide'
|
|
136
139
|
let hideheader = sb.get(accountSetting, 'header.hidden', false)
|
|
@@ -709,9 +712,8 @@ export default class Widget extends Com {
|
|
|
709
712
|
sb.setTimeout(() => $input && $input.blur(), 300) // force lose focus
|
|
710
713
|
}
|
|
711
714
|
|
|
712
|
-
focusInput() {
|
|
715
|
+
focusInput(text) {
|
|
713
716
|
if (this.props.store.isPreview) return
|
|
714
|
-
|
|
715
717
|
if (this.shouldShowForm()) {
|
|
716
718
|
// focus on the element
|
|
717
719
|
let firstemptykey = ''
|
|
@@ -733,6 +735,9 @@ export default class Widget extends Com {
|
|
|
733
735
|
|
|
734
736
|
var $input = this.msgInput.current
|
|
735
737
|
if (!$input) return
|
|
738
|
+
if (text != undefined && typeof text === 'string') {
|
|
739
|
+
$input.applyMessage(text)
|
|
740
|
+
}
|
|
736
741
|
sb.setTimeout(() => $input.focus())
|
|
737
742
|
sb.setTimeout(() => $input.focus(), 300) // force focus
|
|
738
743
|
}
|
|
@@ -770,17 +775,21 @@ export default class Widget extends Com {
|
|
|
770
775
|
})
|
|
771
776
|
if (_creating != this._creating) return // outdated
|
|
772
777
|
if (error) {
|
|
778
|
+
this.setState({creating: false})
|
|
779
|
+
return
|
|
773
780
|
// show error and try again
|
|
774
781
|
}
|
|
775
782
|
await this.props.store.sendConvoEvent(convo.id, 'message_sent', {message})
|
|
776
783
|
if (_creating != this._creating) return // outdated
|
|
777
|
-
this.setState({creating: false})
|
|
778
|
-
|
|
779
784
|
this.props.onGo({view: 'chat', cid: convo.id})
|
|
785
|
+
this.setState({creating: false})
|
|
780
786
|
return
|
|
781
787
|
}
|
|
782
|
-
|
|
783
|
-
|
|
788
|
+
// dont let text-input wait, since we want to clear out the message as soon as posible
|
|
789
|
+
sb.setTimeout(async () => {
|
|
790
|
+
await this.props.store.sendConvoEvent(this.props.cid, 'message_sent', {message})
|
|
791
|
+
this.setState({creating: false})
|
|
792
|
+
}, 1)
|
|
784
793
|
}
|
|
785
794
|
|
|
786
795
|
createPostback(postback) {
|
|
@@ -798,6 +807,7 @@ export default class Widget extends Com {
|
|
|
798
807
|
ref={this.msgInput}
|
|
799
808
|
cid={this.props.cid}
|
|
800
809
|
onChange={this.onChangeMessageInput}
|
|
810
|
+
is_loading={this.state.creating}
|
|
801
811
|
onSend={this.sendMessage}
|
|
802
812
|
t={this.props.t}
|
|
803
813
|
/>
|
|
@@ -812,7 +822,6 @@ export default class Widget extends Com {
|
|
|
812
822
|
</div>
|
|
813
823
|
)
|
|
814
824
|
}
|
|
815
|
-
|
|
816
825
|
return (
|
|
817
826
|
<div class='widget-body'>
|
|
818
827
|
<div class='widget-body--content' onClick={(e) => this.onContainerClick(e)}>
|
|
@@ -822,19 +831,13 @@ export default class Widget extends Com {
|
|
|
822
831
|
store={this.props.store}
|
|
823
832
|
chatbox={this.props.plugin.chatbox || {}}
|
|
824
833
|
onFormSubmit={(e) => this.onEventFormSubmit(e)}
|
|
825
|
-
ref={(ref) => (this
|
|
834
|
+
ref={(ref) => (this.$events = ref)}
|
|
826
835
|
cid={this.props.cid}
|
|
827
836
|
creating={this.creating}
|
|
828
837
|
onSend={(e) => this.sendMessage(e)}
|
|
829
838
|
onPostback={(e) => this.createPostback(e)}
|
|
830
839
|
t={this.props.t}
|
|
831
|
-
/>
|
|
832
|
-
<Typing
|
|
833
|
-
store={this.props.store}
|
|
834
|
-
cid={this.props.cid}
|
|
835
|
-
t={this.props.t}
|
|
836
840
|
plugin={this.props.plugin}
|
|
837
|
-
ref={this.refTyping}
|
|
838
841
|
/>
|
|
839
842
|
</div>
|
|
840
843
|
<Rating
|
package/src/chatbox/main.js
CHANGED
|
@@ -168,6 +168,10 @@ export default class Main extends Com {
|
|
|
168
168
|
this.props.store.setLastview(p.view, {cid: p.cid})
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
applyMessage(text) {
|
|
172
|
+
this.refWidget.current && this.refWidget.current.applyMessage(text)
|
|
173
|
+
}
|
|
174
|
+
|
|
171
175
|
showGreeting() {
|
|
172
176
|
this.refButton.current && this.refButton.current.ShowGreeting()
|
|
173
177
|
}
|