From 61e0586c9078206ef66baf5182ba72debeb419a1 Mon Sep 17 00:00:00 2001 From: Eugene Date: Thu, 31 Oct 2024 18:37:29 +0000 Subject: [PATCH] Fix: avatar display in various scenarios --- .../createDefaultGroupActivitiesMiddleware.ts | 59 ++++++++++--------- packages/component/src/Avatar/ImageAvatar.tsx | 11 ++-- .../Avatar/createCoreMiddleware.tsx | 2 +- .../src/Styles/StyleSet/ImageAvatar.ts | 3 +- 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/packages/api/src/hooks/middleware/createDefaultGroupActivitiesMiddleware.ts b/packages/api/src/hooks/middleware/createDefaultGroupActivitiesMiddleware.ts index 23d81d3162..85f163b76e 100644 --- a/packages/api/src/hooks/middleware/createDefaultGroupActivitiesMiddleware.ts +++ b/packages/api/src/hooks/middleware/createDefaultGroupActivitiesMiddleware.ts @@ -8,7 +8,7 @@ function bin(items: T[], grouping: (last: T, current: T) => boolean): T[][] { const bins: T[][] = []; let lastItem: T; - items.forEach(item => { + for (const item of items) { if (lastItem && grouping(lastItem, item)) { lastBin.push(item); } else { @@ -17,7 +17,7 @@ function bin(items: T[], grouping: (last: T, current: T) => boolean): T[][] { } lastItem = item; - }); + } return bins; } @@ -25,38 +25,43 @@ function bin(items: T[], grouping: (last: T, current: T) => boolean): T[][] { function sending(activity: WebChatActivity): SendStatus | undefined { if (activity.from.role === 'user') { const { - channelData: { state, 'webchat:send-status': sendStatus } + channelData: { 'webchat:send-status': sendStatus } } = activity; - // `channelData.state` is being deprecated in favor of `channelData['webchat:send-status']`. - // Please refer to #4362 for details. Remove on or after 2024-07-31. - return sendStatus || (state === 'sent' ? 'sent' : 'sending'); + return sendStatus; } } -function shouldGroupTimestamp( - activityX: WebChatActivity, - activityY: WebChatActivity, - groupTimestamp: boolean | number, - { Date }: GlobalScopePonyfill -): boolean { - if (groupTimestamp === false) { - // Hide timestamp for all activities. - return true; - } else if (activityX && activityY) { - if (sending(activityX) !== sending(activityY)) { - return false; - } +function createShouldGroupTimestamp(groupTimestamp: boolean | number, { Date }: GlobalScopePonyfill) { + return (activityX: WebChatActivity, activityY: WebChatActivity): boolean => { + if (groupTimestamp === false) { + // Hide timestamp for all activities. + return true; + } else if (activityX && activityY) { + if (sending(activityX) !== sending(activityY)) { + return false; + } - groupTimestamp = typeof groupTimestamp === 'number' ? groupTimestamp : Infinity; + groupTimestamp = typeof groupTimestamp === 'number' ? groupTimestamp : Infinity; - const timeX = new Date(activityX.timestamp).getTime(); - const timeY = new Date(activityY.timestamp).getTime(); + const timeX = new Date(activityX.timestamp).getTime(); + const timeY = new Date(activityY.timestamp).getTime(); - return Math.abs(timeX - timeY) <= groupTimestamp; - } + return Math.abs(timeX - timeY) <= groupTimestamp; + } + + return false; + }; +} - return false; +function shouldGroupSender(x: WebChatActivity, y: WebChatActivity): boolean { + const { + from: { role: roleX, id: idX } + } = x; + const { + from: { role: roleY, id: idY } + } = y; + return roleX === roleY && idX === idY; } export default function createDefaultGroupActivitiesMiddleware({ @@ -69,7 +74,7 @@ export default function createDefaultGroupActivitiesMiddleware({ return () => () => ({ activities }) => ({ - sender: bin(activities, (x, y) => x.from.role === y.from.role), - status: bin(activities, (x, y) => shouldGroupTimestamp(x, y, groupTimestamp, ponyfill)) + sender: bin(activities, shouldGroupSender), + status: bin(activities, createShouldGroupTimestamp(groupTimestamp, ponyfill)) }); } diff --git a/packages/component/src/Avatar/ImageAvatar.tsx b/packages/component/src/Avatar/ImageAvatar.tsx index 83a440fbbd..6a5462aef1 100644 --- a/packages/component/src/Avatar/ImageAvatar.tsx +++ b/packages/component/src/Avatar/ImageAvatar.tsx @@ -2,7 +2,6 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import React, { memo } from 'react'; -import FixedWidthImage from '../Utils/FixedWidthImage'; import useStyleSet from '../hooks/useStyleSet'; import { useStyleToEmotionObject } from '../hooks/internal/styleToEmotionObject'; @@ -10,7 +9,9 @@ const { useAvatarForBot, useAvatarForUser } = hooks; const ROOT_STYLE = { '& .webchat__imageAvatar__image': { - width: '100%' + width: '100%', + height: '100%', + objectFit: 'cover' } }; @@ -25,11 +26,7 @@ const ImageAvatar = memo(({ fromUser }: Readonly<{ fromUser: boolean }>) => { return ( !!avatarImage && (
- +
) ); diff --git a/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx b/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx index 1f015eb364..07863132f0 100644 --- a/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx +++ b/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx @@ -9,7 +9,7 @@ import useStyleSet from '../../hooks/useStyleSet'; import { useStyleToEmotionObject } from '../../hooks/internal/styleToEmotionObject'; const ROOT_STYLE = { - overflow: 'hidden', + overflow: ['hidden', 'clip'], position: 'relative', '> *': { diff --git a/packages/component/src/Styles/StyleSet/ImageAvatar.ts b/packages/component/src/Styles/StyleSet/ImageAvatar.ts index 3dfc919a1f..112a03e423 100644 --- a/packages/component/src/Styles/StyleSet/ImageAvatar.ts +++ b/packages/component/src/Styles/StyleSet/ImageAvatar.ts @@ -2,8 +2,9 @@ import CSSTokens from '../CSSTokens'; export default function createImageAvatarStyle() { return { + aspectRatio: 1, height: CSSTokens.SizeAvatar, - overflow: 'hidden', + overflow: ['hidden', 'clip'], width: CSSTokens.SizeAvatar }; }