Skip to content

Commit 2fc4f5c

Browse files
authored
Fix: avatar display in various scenarios (#5346)
* Fix: avatar display in various scenarios * Update tests * Add tests * Changelog * Center vertically and use responsive image for avatar
1 parent 8ac01bf commit 2fc4f5c

20 files changed

+714
-47
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
9090
- Moved to `micromark` for rendering Markdown, instead of `markdown-it`, in PR [#5330](https://github.com/microsoft/BotFramework-WebChat/pull/5330), by [@compulim](https://github.com/compulim)
9191
- Improved view code dialog UI in Fluent theme with better styling and accessibility, in PR [#5337](https://github.com/microsoft/BotFramework-WebChat/pull/5337), by [@OEvgeny](https://github.com/OEvgeny)
9292
- Switched math block syntax from `$$` to Tex-style `\[ \]` and `\( \)` delimiters with improved rendering and error handling, in PR [#5353](https://github.com/microsoft/BotFramework-WebChat/pull/5353), by [@OEvgeny](https://github.com/OEvgeny)
93+
- Improved avatar display and grouping behavior by fixing rendering issues and activity sender identification, in PR [#5346](https://github.com/microsoft/BotFramework-WebChat/pull/5346), by [@OEvgeny](https://github.com/OEvgeny)
9394

9495
### Fixed
9596

__tests__/html/autoScroll.withPostBack.activity.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@
101101
}
102102
],
103103
from: {
104-
id: 'bot',
105104
role: 'bot'
106105
},
107106
id: '1',

__tests__/html/autoScroll.withPostBack.page.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@
101101
}
102102
],
103103
from: {
104-
id: 'bot',
105104
role: 'bot'
106105
},
107106
id: '1',

__tests__/html/typing/activityOrder.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
// SETUP: Bot sent a message.
5252
await directLine.emulateIncomingActivity({
5353
id: 'a-00001',
54+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
5455
text: 'Adipisicing cupidatat eu Lorem anim ut aute magna occaecat id cillum.',
5556
type: 'message'
5657
});
@@ -91,6 +92,7 @@
9192
// WHEN: Bot send another message.
9293
await directLine.emulateIncomingActivity({
9394
id: 'a-00003',
95+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
9496
text: 'Amet consequat enim incididunt excepteur aliquip magna duis et tempor.',
9597
type: 'message'
9698
});

__tests__/html/typing/chunk.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
// SETUP: Bot sent a message.
5252
await directLine.emulateIncomingActivity({
5353
id: 'a-00001',
54+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
5455
text: 'Adipisicing cupidatat eu Lorem anim ut aute magna occaecat id cillum.',
5556
type: 'message'
5657
});

__tests__/html/typing/informative.html

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,14 @@
3333

3434
await pageConditions.uiConnected();
3535

36-
await directLine.emulateIncomingActivity(
37-
'Adipisicing cupidatat eu Lorem anim ut aute magna occaecat id cillum.'
38-
);
36+
await directLine.emulateIncomingActivity({
37+
from: {
38+
id: 'u-00001',
39+
name: 'Bot',
40+
role: 'bot'
41+
},
42+
text: 'Adipisicing cupidatat eu Lorem anim ut aute magna occaecat id cillum.'
43+
});
3944

4045
const firstTypingActivityId = 't-00001';
4146

__tests__/html/typing/outOfOrder.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
// SETUP: Bot sent a message.
5656
await directLine.emulateIncomingActivity({
5757
id: 'a-00001',
58+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
5859
text: 'Adipisicing cupidatat eu Lorem anim ut aute magna occaecat id cillum.',
5960
timestamp: 0,
6061
type: 'message'

__tests__/html/typing/outOfOrder.sequenceNumber.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
// SETUP: Bot sent a message.
5656
await directLine.emulateIncomingActivity({
5757
id: 'a-00001',
58+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
5859
text: 'Adipisicing cupidatat eu Lorem anim ut aute magna occaecat id cillum.',
5960
timestamp: 0,
6061
type: 'message'

__tests__/html/typing/simultaneous.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
// WHEN: Bot is typing a message.
6161
await directLine.emulateIncomingActivity({
6262
channelData: { streamSequence: 1, streamType: 'streaming' },
63-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
63+
from: { name: 'Bot', role: 'bot' },
6464
id: 't-00001',
6565
text: 'A quick',
6666
type: 'typing'
@@ -89,7 +89,7 @@
8989
// WHEN: Bot is typing another message.
9090
await directLine.emulateIncomingActivity({
9191
channelData: { streamSequence: 1, streamType: 'streaming' },
92-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
92+
from: { name: 'Bot', role: 'bot' },
9393
id: 't-10001',
9494
text: 'Falsches Üben',
9595
type: 'typing'
@@ -120,7 +120,7 @@
120120
// WHEN: Bot continue typing the message.
121121
await directLine.emulateIncomingActivity({
122122
channelData: { streamSequence: 2, streamId: 't-00001', streamType: 'streaming' },
123-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
123+
from: { name: 'Bot', role: 'bot' },
124124
id: 't-00002',
125125
text: 'A quick brown fox',
126126
type: 'typing'
@@ -149,7 +149,7 @@
149149
// WHEN: Bot continue typing the third message.
150150
await directLine.emulateIncomingActivity({
151151
channelData: { streamSequence: 2, streamId: 't-10001', streamType: 'streaming' },
152-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
152+
from: { name: 'Bot', role: 'bot' },
153153
id: 't-10002',
154154
text: 'Falsches Üben von Xylophonmusik',
155155
type: 'typing'
@@ -178,7 +178,7 @@
178178
// WHEN: Bot finished typing the second message.
179179
await directLine.emulateIncomingActivity({
180180
channelData: { streamSequence: 3, streamId: 't-00001', streamType: 'streaming' },
181-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
181+
from: { name: 'Bot', role: 'bot' },
182182
id: 'a-00002',
183183
text: 'A quick brown fox jumped over the lazy dogs.',
184184
type: 'message'
@@ -210,7 +210,7 @@
210210
// WHEN: Bot finished typing the third message.
211211
await directLine.emulateIncomingActivity({
212212
channelData: { streamSequence: 3, streamId: 't-10001', streamType: 'streaming' },
213-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
213+
from: { name: 'Bot', role: 'bot' },
214214
id: 'a-00003',
215215
text: 'Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.',
216216
type: 'message'
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
<!doctype html>
2+
<html lang="en-US">
3+
<head>
4+
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
5+
<script crossorigin="anonymous" src="https://unpkg.com/@babel/standalone@7.8.7/babel.min.js"></script>
6+
<script crossorigin="anonymous" src="https://unpkg.com/react@16.8.6/umd/react.development.js"></script>
7+
<script crossorigin="anonymous" src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.development.js"></script>
8+
<script crossorigin="anonymous" src="/test-harness.js"></script>
9+
<script crossorigin="anonymous" src="/test-page-object.js"></script>
10+
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
11+
</head>
12+
<template id="avatars">
13+
<svg data-for="1" xmlns="http://www.w3.org/2000/svg" width="75" height="150" viewBox="0 0 75 150">
14+
<!-- Gradient Definitions -->
15+
<defs>
16+
<linearGradient id="tallGradient" x1="0%" y1="0%" x2="100%" y2="100%">
17+
<stop offset="0%" style="stop-color:#0ea5e9"/>
18+
<stop offset="100%" style="stop-color:#6366f1"/>
19+
</linearGradient>
20+
<linearGradient id="tallHighlight" x1="0%" y1="0%" x2="100%" y2="100%">
21+
<stop offset="0%" style="stop-color:rgba(255,255,255,0.2)"/>
22+
<stop offset="100%" style="stop-color:rgba(255,255,255,0)"/>
23+
</linearGradient>
24+
</defs>
25+
26+
<!-- Base Rectangle -->
27+
<rect width="75" height="150" rx="37.5" fill="url(#tallGradient)"/>
28+
29+
<!-- Highlight Overlay -->
30+
<path d="M 0 0 L 75 0 L 75 75 Q 37.5 95 0 75 Z" fill="url(#tallHighlight)" opacity="0.5"/>
31+
32+
<!-- Face - Positioned in Upper Third -->
33+
<!-- Eyes -->
34+
<path d="M 25 55 Q 27 52 29 55" stroke="white" stroke-width="3" stroke-linecap="round" fill="none"/>
35+
<path d="M 46 55 Q 48 52 50 55" stroke="white" stroke-width="3" stroke-linecap="round" fill="none"/>
36+
37+
<!-- Smile -->
38+
<path d="M 25 70 Q 37.5 80 50 70" stroke="white" stroke-width="3" stroke-linecap="round" fill="none"/>
39+
40+
<!-- Decorative Elements -->
41+
<circle cx="37.5" cy="110" r="15" stroke="white" stroke-width="3" fill="none" opacity="0.3"/>
42+
<circle cx="37.5" cy="110" r="7" stroke="white" stroke-width="2" fill="none" opacity="0.2"/>
43+
</svg>
44+
<svg data-for="2" xmlns="http://www.w3.org/2000/svg" width="150" height="75" viewBox="0 0 150 75">
45+
<!-- Gradient Definitions -->
46+
<defs>
47+
<linearGradient id="wideGradient" x1="0%" y1="0%" x2="100%" y2="100%">
48+
<stop offset="0%" style="stop-color:#84cc16"/>
49+
<stop offset="100%" style="stop-color:#22c55e"/>
50+
</linearGradient>
51+
<linearGradient id="wideHighlight" x1="0%" y1="0%" x2="100%" y2="100%">
52+
<stop offset="0%" style="stop-color:rgba(255,255,255,0.25)"/>
53+
<stop offset="100%" style="stop-color:rgba(255,255,255,0)"/>
54+
</linearGradient>
55+
</defs>
56+
57+
<!-- Base Rectangle -->
58+
<rect width="150" height="75" rx="37.5" fill="url(#wideGradient)"/>
59+
60+
<!-- Highlight Overlay -->
61+
<path d="M 0 0 Q 75 -10 150 0 L 150 40 Q 75 30 0 40 Z" fill="url(#wideHighlight)" opacity="0.5"/>
62+
63+
<!-- Face - Centered -->
64+
<!-- Eyes -->
65+
<path d="M 55 35 Q 58 32 61 35" stroke="white" stroke-width="3" stroke-linecap="round" fill="none"/>
66+
<path d="M 89 35 Q 92 32 95 35" stroke="white" stroke-width="3" stroke-linecap="round" fill="none"/>
67+
68+
<!-- Smile -->
69+
<path d="M 55 45 Q 75 55 95 45" stroke="white" stroke-width="3" stroke-linecap="round" fill="none"/>
70+
71+
<!-- Decorative Elements -->
72+
<circle cx="30" cy="37.5" r="8" stroke="white" stroke-width="2" fill="none" opacity="0.2"/>
73+
<circle cx="120" cy="37.5" r="8" stroke="white" stroke-width="2" fill="none" opacity="0.2"/>
74+
</svg>
75+
</template>
76+
<body>
77+
<main id="webchat"></main>
78+
<script type="text/babel" data-presets="env,stage-3,react">
79+
const {
80+
React: { useMemo },
81+
WebChat: {
82+
hooks: { useDirection }
83+
}
84+
} = window;
85+
86+
run(async function () {
87+
await host.windowSize(undefined, 1280, document.getElementById('webchat'));
88+
89+
WebChat.renderWebChat(
90+
{
91+
directLine: await testHelpers.createDirectLineWithTranscript([
92+
{
93+
from: { role: 'bot' },
94+
id: '1.0',
95+
text: 'Cillum ea irure amet reprehenderit minim.',
96+
timestamp: -300001,
97+
type: 'message'
98+
},
99+
{
100+
from: { role: 'bot' },
101+
id: '1.1',
102+
text: 'Minim ut laboris enim nostrud magna irure occaecat laborum occaecat ex.',
103+
timestamp: -300001,
104+
type: 'message'
105+
},
106+
{
107+
channelData: { state: 'sent' },
108+
from: { role: 'user' },
109+
id: '2.0',
110+
text: 'Tempor deserunt ut enim eu elit.',
111+
timestamp: -300001,
112+
type: 'message'
113+
},
114+
{
115+
channelData: { state: 'sent' },
116+
from: { role: 'user' },
117+
id: '2.1',
118+
text: 'Elit occaecat quis velit qui ad.',
119+
timestamp: -300001,
120+
type: 'message'
121+
},
122+
{
123+
from: { role: 'bot' },
124+
id: '3.0',
125+
text: 'Nulla irure laborum officia tempor aute consequat eiusmod nisi velit ipsum magna.',
126+
timestamp: -300001,
127+
type: 'message'
128+
},
129+
{
130+
from: { role: 'bot' },
131+
id: '3.1',
132+
text: 'Minim fugiat aute do ea veniam.',
133+
timestamp: -300001,
134+
type: 'message'
135+
},
136+
{
137+
channelData: { state: 'sent' },
138+
from: { role: 'user' },
139+
id: '4.0',
140+
text: 'This first activity has user avatar',
141+
timestamp: 0,
142+
type: 'message'
143+
},
144+
{
145+
channelData: { state: 'sent' },
146+
from: { role: 'user' },
147+
id: '4.1',
148+
text: 'This shows no avatar as the activities in the same group',
149+
timestamp: 0,
150+
type: 'message'
151+
},
152+
{
153+
attachmentLayout: 'carousel',
154+
attachments: [
155+
{
156+
contentType: 'image/jpeg',
157+
contentUrl:
158+
'https://raw.githubusercontent.com/compulim/BotFramework-MockBot/master/public/assets/surface1.jpg',
159+
name: 'front of Surface Pro'
160+
},
161+
{
162+
contentType: 'image/jpeg',
163+
contentUrl:
164+
'https://raw.githubusercontent.com/compulim/BotFramework-MockBot/master/public/assets/surface2.jpg',
165+
name: 'back of Surface Pro'
166+
}
167+
],
168+
from: { role: 'bot' },
169+
id: '5.0',
170+
text: 'Bot message with attachment',
171+
timestamp: 0,
172+
type: 'message'
173+
},
174+
{
175+
from: { role: 'bot' },
176+
id: '5.1',
177+
text: 'Follow-up message within the group',
178+
timestamp: 0,
179+
type: 'message'
180+
}
181+
]),
182+
store: testHelpers.createStore(),
183+
styleOptions: {
184+
botAvatarImage: `data:image/svg+xml;utf8,${encodeURIComponent(window.avatars.content.querySelector(`[data-for="1"]`).outerHTML)}`,
185+
botAvatarInitials: 'Bot',
186+
bubbleBackground: '#0063B1',
187+
bubbleBorderColor: '#0063B1',
188+
bubbleBorderRadius: 4,
189+
bubbleFromUserBackground: '#0063B1',
190+
bubbleFromUserBorderColor: '#0063B1',
191+
bubbleFromUserBorderRadius: 4,
192+
bubbleFromUserNubOffset: 0,
193+
bubbleFromUserNubSize: 10,
194+
bubbleFromUserTextColor: 'White',
195+
bubbleNubOffset: 0,
196+
bubbleNubSize: 10,
197+
bubbleTextColor: 'White',
198+
userAvatarInitials: 'You',
199+
userAvatarImage: `data:image/svg+xml;utf8,${encodeURIComponent(window.avatars.content.querySelector(`[data-for="2"]`).outerHTML)}`,
200+
}
201+
},
202+
document.getElementById('webchat')
203+
);
204+
205+
await pageConditions.uiConnected();
206+
207+
await host.snapshot('local');
208+
});
209+
</script>
210+
</body>
211+
</html>
Loading

0 commit comments

Comments
 (0)