@subiz/widget-v4 4.1.117 → 4.1.120
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 +36 -18
- package/assets/less/widget_header.less +35 -36
- package/compiled_src/chatbox/AgentsAvatar.js +1 -1
- package/compiled_src/chatbox/Event.js +87 -13
- package/compiled_src/chatbox/Events.js +106 -19
- package/compiled_src/chatbox/Header.js +5 -4
- package/compiled_src/chatbox/InfoMessage.js +2 -13
- package/compiled_src/chatbox/MessageInput.js +19 -9
- package/compiled_src/chatbox/TextMessage.js +11 -2
- package/compiled_src/chatbox/Widget.js +28 -23
- package/compiled_src/chatbox/time.js +1 -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 +2 -2
- package/src/chatbox/AgentsAvatar.js +1 -1
- package/src/chatbox/Event.js +88 -14
- package/src/chatbox/Events.js +93 -15
- package/src/chatbox/Header.js +3 -2
- package/src/chatbox/InfoMessage.js +0 -14
- package/src/chatbox/MessageInput.js +18 -7
- package/src/chatbox/TextMessage.js +13 -0
- package/src/chatbox/Widget.js +16 -18
- package/src/chatbox/time.js +12 -8
- 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.120",
|
|
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
|
},
|
|
@@ -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,87 @@ export default class Event extends Com {
|
|
|
149
152
|
})
|
|
150
153
|
}
|
|
151
154
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
155
|
+
renderTyping() {
|
|
156
|
+
if (!this.props.event.is_show) {
|
|
157
|
+
return (
|
|
158
|
+
<div key={'container'} class='convo-event agent-message' style='opacity: 0 !important'>
|
|
159
|
+
<div class='agent-convo-event-wrapper'>
|
|
160
|
+
<div class='agent-convo-event-inner'>
|
|
161
|
+
<div class='message-agent message-text--agent' style='opacity: 0.6 !important'>
|
|
162
|
+
<div style='height: 20px !important; width: 35px !important'></div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
160
166
|
</div>
|
|
161
167
|
)
|
|
162
168
|
}
|
|
163
|
-
if (this.props.store.isAIDevMode()) $time = null
|
|
164
169
|
|
|
170
|
+
var html = `
|
|
171
|
+
<html>
|
|
172
|
+
<head>
|
|
173
|
+
<style>
|
|
174
|
+
.typing-container {
|
|
175
|
+
width: 100vw;
|
|
176
|
+
height: 100vh;
|
|
177
|
+
display: flex;
|
|
178
|
+
align-items: center;
|
|
179
|
+
gap: 4px;
|
|
180
|
+
justify-content: center;
|
|
181
|
+
}
|
|
182
|
+
.typing-dot {
|
|
183
|
+
display: inline-block;
|
|
184
|
+
vertical-align: middle;
|
|
185
|
+
width: 8px;
|
|
186
|
+
height: 8px;
|
|
187
|
+
background: black;
|
|
188
|
+
border-radius: 50%;
|
|
189
|
+
animation: typing 0.5s infinite alternate;
|
|
190
|
+
}
|
|
191
|
+
.typing-dot:nth-of-type(2) {
|
|
192
|
+
animation-delay: 0.2s;
|
|
193
|
+
}
|
|
194
|
+
.typing-dot:nth-of-type(3) {
|
|
195
|
+
animation-delay: 0.6s;
|
|
196
|
+
}
|
|
197
|
+
@keyframes typing {
|
|
198
|
+
0% {
|
|
199
|
+
opacity: 0.9;
|
|
200
|
+
}
|
|
201
|
+
100% {
|
|
202
|
+
opacity: 0.4;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
</style>
|
|
206
|
+
</head>
|
|
207
|
+
<body style="padding: 0; margin: 0">
|
|
208
|
+
<div class="typing-container">
|
|
209
|
+
<span class="typing-dot"></span>
|
|
210
|
+
<span class="typing-dot"></span>
|
|
211
|
+
<span class="typing-dot"></span>
|
|
212
|
+
</div>
|
|
213
|
+
</body>
|
|
214
|
+
</html>
|
|
215
|
+
`
|
|
216
|
+
let src = 'data:text/html,' + encodeURIComponent(html)
|
|
217
|
+
return (
|
|
218
|
+
<div key={'container'} class='convo-event agent-message' style='opacity: 0.6 !important'>
|
|
219
|
+
<div class='agent-convo-event-wrapper'>
|
|
220
|
+
<div class='agent-convo-event-inner'>
|
|
221
|
+
<div class='message-agent message-text--agent'>
|
|
222
|
+
<iframe
|
|
223
|
+
src={src}
|
|
224
|
+
style='width: 35px !important; height: 20px !important; display: block !important; overflow: hidden !important; padding: 0 !important '
|
|
225
|
+
></iframe>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
renderMessageSent() {
|
|
234
|
+
let ev = this.props.event.ev
|
|
235
|
+
this.tryLoadOrder(ev)
|
|
165
236
|
let t = new sb.Date(ev.created).toLocaleString()
|
|
166
237
|
// message of agent
|
|
167
238
|
if (sb.get(ev, 'by.type') !== 'user') {
|
|
@@ -171,11 +242,16 @@ export default class Event extends Com {
|
|
|
171
242
|
if (this.props.isLast) innercls += ' last'
|
|
172
243
|
return (
|
|
173
244
|
<div class='convo-event agent-message'>
|
|
174
|
-
{$time}
|
|
175
245
|
{$sender}
|
|
176
246
|
<div class='agent-convo-event-wrapper'>
|
|
177
247
|
<div class={innercls}>
|
|
178
|
-
<TextMessage
|
|
248
|
+
<TextMessage
|
|
249
|
+
showTime={this.props.event.show_time}
|
|
250
|
+
isLast={this.props.isLast}
|
|
251
|
+
store={this.props.store}
|
|
252
|
+
ev={ev}
|
|
253
|
+
onLink={this.props.onLink}
|
|
254
|
+
/>
|
|
179
255
|
<ImageAttachments store={this.props.store} ev={ev} />
|
|
180
256
|
<AudioAttachments store={this.props.store} ev={ev} />
|
|
181
257
|
<VideoAttachments store={this.props.store} ev={ev} />
|
|
@@ -223,7 +299,7 @@ export default class Event extends Com {
|
|
|
223
299
|
}
|
|
224
300
|
|
|
225
301
|
let $sender = null
|
|
226
|
-
if (this.props.event.mode === 'lead') $sender = <div class='pt-
|
|
302
|
+
if (this.props.event.mode === 'lead') $sender = <div class='pt-2'></div>
|
|
227
303
|
|
|
228
304
|
let $error = null
|
|
229
305
|
if (ev._error && ev.type === 'message_sent') {
|
|
@@ -239,7 +315,6 @@ export default class Event extends Com {
|
|
|
239
315
|
|
|
240
316
|
return (
|
|
241
317
|
<div class='convo-event user-message'>
|
|
242
|
-
{$time}
|
|
243
318
|
{$sender}
|
|
244
319
|
<div class='message-user__container'>
|
|
245
320
|
{$dot}
|
|
@@ -307,7 +382,6 @@ export default class Event extends Com {
|
|
|
307
382
|
|
|
308
383
|
renderReactions() {
|
|
309
384
|
if (this.props.store.isAIDevMode()) return null
|
|
310
|
-
|
|
311
385
|
let ev = sb.get(this.props.event, 'ev') || {}
|
|
312
386
|
let pongs = sb.get(ev, 'data.message.pongs') || []
|
|
313
387
|
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,26 @@ 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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
113
|
+
// console.log('-----------', this.state.isShowTyping, this.state.typing_event)
|
|
114
|
+
let ev = this.state.typing_event || {id: 'evzz' + sb.Date.now(), created: sb.Date.now(), by: {type: 'agent'}}
|
|
115
|
+
let fakeev = {
|
|
116
|
+
is_typing: true,
|
|
117
|
+
is_show: this.state.isShowTyping,
|
|
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
|
+
},
|
|
66
126
|
}
|
|
127
|
+
events.push(fakeev)
|
|
128
|
+
processEvents(convo, events)
|
|
67
129
|
|
|
68
130
|
let $events = sb.map(events, (ev) => {
|
|
69
|
-
let isLast = ev.ev.id ===
|
|
131
|
+
let isLast = ev.ev.id === sb.get(convo, 'last_message_sent.id')
|
|
70
132
|
return (
|
|
71
133
|
<Event
|
|
72
134
|
isLast={isLast}
|
|
@@ -85,11 +147,18 @@ export default class Events extends Com {
|
|
|
85
147
|
|
|
86
148
|
let $loading = null
|
|
87
149
|
let style = 'opacity: 1 !important'
|
|
88
|
-
if (this.
|
|
150
|
+
if (this.props.creating) {
|
|
89
151
|
$loading = <Spinner static mode={sb.get(this.props.chatbox, 'primary_color', 'dark')} size='120' center />
|
|
90
152
|
style = 'opacity: 0 !important'
|
|
91
153
|
}
|
|
92
154
|
|
|
155
|
+
if (this.state.loading) {
|
|
156
|
+
if (sb.Date.now() - this.state.loading > 500) {
|
|
157
|
+
$loading = <Spinner static mode={sb.get(this.props.chatbox, 'primary_color', 'dark')} size='120' center />
|
|
158
|
+
style = 'opacity: 0 !important'
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
93
162
|
return (
|
|
94
163
|
<Fragment>
|
|
95
164
|
{$loading}
|
|
@@ -171,9 +240,13 @@ export default class Events extends Com {
|
|
|
171
240
|
if (!this.props.cid) return
|
|
172
241
|
// load msg
|
|
173
242
|
this.lastContentOffsetY = 0
|
|
174
|
-
this.setState({loading:
|
|
243
|
+
this.setState({loading: false})
|
|
175
244
|
let events = this.props.store.listEvents(this.props.cid)
|
|
176
245
|
if (sb.size(events) === 0) {
|
|
246
|
+
this.setState({loading: sb.Date.now()})
|
|
247
|
+
sb.setTimeout(() => {
|
|
248
|
+
this.forceUpdate()
|
|
249
|
+
}, 800)
|
|
177
250
|
let cid = this.props.cid
|
|
178
251
|
|
|
179
252
|
let {error} = await this.props.store.fetchMoreEvents(cid)
|
|
@@ -184,11 +257,10 @@ export default class Events extends Com {
|
|
|
184
257
|
return
|
|
185
258
|
}
|
|
186
259
|
}
|
|
187
|
-
this.setState({loading: true})
|
|
188
260
|
this.props.store.fetchMoreEvents(this.props.cid)
|
|
189
261
|
this.setState({error: false})
|
|
190
262
|
this.scrollToBottom()
|
|
191
|
-
sb.setTimeout(() => this.setState({loading: false}), 50)
|
|
263
|
+
// sb.setTimeout(() => this.setState({loading: false}), 50)
|
|
192
264
|
}
|
|
193
265
|
|
|
194
266
|
isBottom() {
|
|
@@ -205,7 +277,7 @@ export default class Events extends Com {
|
|
|
205
277
|
sb.setTimeout(() => {
|
|
206
278
|
const $div = this.refBody
|
|
207
279
|
if ($div) $div.scrollTop = $div.scrollHeight
|
|
208
|
-
},
|
|
280
|
+
}, 100)
|
|
209
281
|
|
|
210
282
|
if (this.props.isShow) {
|
|
211
283
|
if (this.props.store.browserVisibility === 'visible' && document.hasFocus()) {
|
|
@@ -224,9 +296,13 @@ function processEvents(convo, events) {
|
|
|
224
296
|
|
|
225
297
|
// show time for the first msg sent
|
|
226
298
|
// insert time
|
|
299
|
+
var lastAgentEvent
|
|
227
300
|
for (var i = 1; i < events.length; i++) {
|
|
228
301
|
let curEvent = events[i]
|
|
229
302
|
let lastEvent = events[i - 1]
|
|
303
|
+
if (sb.get(curEvent, 'ev.by.type') != 'user' && !curEvent.is_typing) {
|
|
304
|
+
lastAgentEvent = curEvent
|
|
305
|
+
}
|
|
230
306
|
|
|
231
307
|
if (visibleEvent(curEvent.ev)) {
|
|
232
308
|
let elapsedSec = sb.unixSec(curEvent.ev.created) - sb.unixSec(lastEvent.ev.created)
|
|
@@ -234,6 +310,8 @@ function processEvents(convo, events) {
|
|
|
234
310
|
}
|
|
235
311
|
}
|
|
236
312
|
|
|
313
|
+
if (lastAgentEvent) lastAgentEvent.show_time = true
|
|
314
|
+
|
|
237
315
|
for (var i = 0; i < events.length; i++) {
|
|
238
316
|
let curEvent = events[i]
|
|
239
317
|
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
|
}
|
|
@@ -324,9 +333,11 @@ export default class MessageInput extends Com {
|
|
|
324
333
|
msg = msg || sb.trim(this.state.msgValue) || ''
|
|
325
334
|
if (!msg) return
|
|
326
335
|
if (this.props.disabled) return
|
|
336
|
+
if (this.props.onSend) {
|
|
337
|
+
await this.props.onSend({text: msg, format: 'plaintext'})
|
|
338
|
+
}
|
|
327
339
|
this.setState({openEmoji: false, msgValue: ''})
|
|
328
340
|
this.resizeInput()
|
|
329
|
-
this.props.onSend && this.props.onSend({text: msg, format: 'plaintext'})
|
|
330
341
|
}
|
|
331
342
|
|
|
332
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'
|
|
@@ -68,7 +67,7 @@ export default class Widget extends Com {
|
|
|
68
67
|
// focus Events then focus MessageInput
|
|
69
68
|
// if there is any pending form, MessageInput will be disabled
|
|
70
69
|
// and dont steal focus from Events
|
|
71
|
-
this
|
|
70
|
+
this.$events && this.$events.focus()
|
|
72
71
|
if (!this.props.store.isMobile()) this.focusInput()
|
|
73
72
|
}, 100)
|
|
74
73
|
this.updateFormDataFields()
|
|
@@ -77,7 +76,7 @@ export default class Widget extends Com {
|
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
ShowTyping() {
|
|
80
|
-
this
|
|
79
|
+
this.$events && this.$events.ShowTyping()
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
shouldShowForm() {
|
|
@@ -625,8 +624,8 @@ export default class Widget extends Com {
|
|
|
625
624
|
<div>{title}</div>
|
|
626
625
|
{this.renderFields(form, formName)}
|
|
627
626
|
</div>
|
|
628
|
-
|
|
629
|
-
|
|
627
|
+
</div>
|
|
628
|
+
<div class="mt-2"></div>
|
|
630
629
|
<PoweredBy store={this.props.store} t={this.props.t} />
|
|
631
630
|
</div>
|
|
632
631
|
|
|
@@ -699,6 +698,7 @@ export default class Widget extends Com {
|
|
|
699
698
|
<span>{this.props.t('start_conversation')}</span>
|
|
700
699
|
<img src={send} alt='send button' width='26' height='26' />
|
|
701
700
|
</button>
|
|
701
|
+
<div class="mt-2"></div>
|
|
702
702
|
<PoweredBy store={this.props.store} />
|
|
703
703
|
</div>
|
|
704
704
|
</div>
|
|
@@ -776,17 +776,21 @@ export default class Widget extends Com {
|
|
|
776
776
|
})
|
|
777
777
|
if (_creating != this._creating) return // outdated
|
|
778
778
|
if (error) {
|
|
779
|
+
this.setState({creating: false})
|
|
780
|
+
return
|
|
779
781
|
// show error and try again
|
|
780
782
|
}
|
|
781
783
|
await this.props.store.sendConvoEvent(convo.id, 'message_sent', {message})
|
|
782
784
|
if (_creating != this._creating) return // outdated
|
|
783
|
-
this.setState({creating: false})
|
|
784
|
-
|
|
785
785
|
this.props.onGo({view: 'chat', cid: convo.id})
|
|
786
|
+
this.setState({creating: false})
|
|
786
787
|
return
|
|
787
788
|
}
|
|
788
|
-
|
|
789
|
-
|
|
789
|
+
// dont let text-input wait, since we want to clear out the message as soon as posible
|
|
790
|
+
sb.setTimeout(async () => {
|
|
791
|
+
await this.props.store.sendConvoEvent(this.props.cid, 'message_sent', {message})
|
|
792
|
+
this.setState({creating: false})
|
|
793
|
+
}, 1)
|
|
790
794
|
}
|
|
791
795
|
|
|
792
796
|
createPostback(postback) {
|
|
@@ -804,6 +808,7 @@ export default class Widget extends Com {
|
|
|
804
808
|
ref={this.msgInput}
|
|
805
809
|
cid={this.props.cid}
|
|
806
810
|
onChange={this.onChangeMessageInput}
|
|
811
|
+
is_loading={this.state.creating}
|
|
807
812
|
onSend={this.sendMessage}
|
|
808
813
|
t={this.props.t}
|
|
809
814
|
/>
|
|
@@ -818,7 +823,6 @@ export default class Widget extends Com {
|
|
|
818
823
|
</div>
|
|
819
824
|
)
|
|
820
825
|
}
|
|
821
|
-
|
|
822
826
|
return (
|
|
823
827
|
<div class='widget-body'>
|
|
824
828
|
<div class='widget-body--content' onClick={(e) => this.onContainerClick(e)}>
|
|
@@ -828,19 +832,13 @@ export default class Widget extends Com {
|
|
|
828
832
|
store={this.props.store}
|
|
829
833
|
chatbox={this.props.plugin.chatbox || {}}
|
|
830
834
|
onFormSubmit={(e) => this.onEventFormSubmit(e)}
|
|
831
|
-
ref={(ref) => (this
|
|
835
|
+
ref={(ref) => (this.$events = ref)}
|
|
832
836
|
cid={this.props.cid}
|
|
833
837
|
creating={this.creating}
|
|
834
838
|
onSend={(e) => this.sendMessage(e)}
|
|
835
839
|
onPostback={(e) => this.createPostback(e)}
|
|
836
840
|
t={this.props.t}
|
|
837
|
-
/>
|
|
838
|
-
<Typing
|
|
839
|
-
store={this.props.store}
|
|
840
|
-
cid={this.props.cid}
|
|
841
|
-
t={this.props.t}
|
|
842
841
|
plugin={this.props.plugin}
|
|
843
|
-
ref={this.refTyping}
|
|
844
842
|
/>
|
|
845
843
|
</div>
|
|
846
844
|
<Rating
|
package/src/chatbox/time.js
CHANGED
|
@@ -28,13 +28,13 @@ export default class Time extends Com {
|
|
|
28
28
|
if (this.props.short) {
|
|
29
29
|
// more than 10 days
|
|
30
30
|
//if (Math.abs(this.props.time - new sb.Date().getTime()) > 86400000 * 10) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
//let tim = new sb.Date(this.props.time)
|
|
32
|
+
//let tzyear = tim.getFullYear()
|
|
33
|
+
//let locale = sb.get(navigator, 'languages.0', 'en-US')
|
|
34
|
+
//if (forceLocale) locale = forceLocale
|
|
35
|
+
//let tzmonthname = tim.toLocaleDateString(locale, {month: 'short'})
|
|
36
|
+
//let tzdate = tim.getDate()
|
|
37
|
+
//t = tzdate + ' ' + tzmonthname + ' ' + tzyear
|
|
38
38
|
//}
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -61,7 +61,11 @@ export default class Time extends Com {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
let title = new Date(this.props.time).toLocaleString(locale)
|
|
64
|
-
return
|
|
64
|
+
return (
|
|
65
|
+
<span class={this.props.class} style={this.props.style} title={title}>
|
|
66
|
+
{this.state.t}
|
|
67
|
+
</span>
|
|
68
|
+
)
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
71
|
|