Skip to content

Commit

Permalink
fix: QA for modularization phase 1 (#353)
Browse files Browse the repository at this point in the history
-

ticket: [AC-3645]

-

Before requesting a code review, please check the following:
- [x] **[Required]** CI has passed all checks.
- [x] **[Required]** A self-review has been conducted to ensure there
are no minor mistakes.
- [x] **[Required]** Unnecessary comments/debugging code have been
removed.
- [x] **[Required]** All requirements specified in the ticket have been
accurately implemented.
- [x] Ensure the ticket has been updated with the sprint, status, and
story points.

[AC-3645]:
https://sendbird.atlassian.net/browse/AC-3645?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
  • Loading branch information
bang9 committed Sep 6, 2024
1 parent 5df34da commit 1b3760f
Show file tree
Hide file tree
Showing 18 changed files with 103 additions and 78 deletions.
7 changes: 3 additions & 4 deletions src/components/BotMessageFeedback.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Feedback, FeedbackRating } from '@sendbird/chat/message';
import { BaseMessage, Feedback, FeedbackRating } from '@sendbird/chat/message';
import { useReducer } from 'react';

import FeedbackIconButton from '@uikit/ui/FeedbackIconButton';
import MessageFeedbackFailedModal from '@uikit/ui/MessageFeedbackFailedModal';
import MessageFeedbackModal from '@uikit/ui/MessageFeedbackModal';
import MobileFeedbackMenu from '@uikit/ui/MobileFeedbackMenu';
import { CoreMessageType } from '@uikit/utils';

import { elementIds } from '../const';
import { useConstantState } from '../context/ConstantContext';
Expand All @@ -17,7 +16,7 @@ type State = Partial<{
menuVisible: boolean;
}>;

function BotMessageFeedback({ message }: { message: CoreMessageType }) {
function BotMessageFeedback({ message }: { message: BaseMessage }) {
const { stringSet } = useConstantState();
const [state, setState] = useReducer((p: State, a: State) => ({ ...p, ...a }), {
errorText: '',
Expand Down Expand Up @@ -104,7 +103,7 @@ function BotMessageFeedback({ message }: { message: CoreMessageType }) {
isMobile
rootElementId={elementIds.widgetWindow}
selectedFeedback={message.myFeedback.rating}
message={message}
message={message as any}
onUpdate={async (selectedFeedback, comment) => {
if (message.myFeedback) {
try {
Expand Down
7 changes: 3 additions & 4 deletions src/components/BotMessageWithBodyInput.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { User } from '@sendbird/chat';
import { ReactNode } from 'react';
import styled from 'styled-components';

import BotProfileImage from './BotProfileImage';
import { useChatContext } from './chat/context/ChatProvider';
import { DefaultSentTime, FullBodyContainer, WideSentTime } from './MessageComponent';
import { useConstantState } from '../context/ConstantContext';
import { Label } from '../foundation/components/Label';
Expand All @@ -12,7 +12,6 @@ const Root = styled.span`
display: flex;
flex-direction: row;
align-items: flex-end;
margin-bottom: 6px;
gap: 8px;
position: relative;
`;
Expand All @@ -38,7 +37,6 @@ const EmptyImageContainer = styled.div`
`;

type Props = {
botUser?: User;
createdAt?: number;
messageData?: string;
bodyComponent: ReactNode;
Expand All @@ -55,9 +53,10 @@ const HEIGHTS = {
};

export default function BotMessageWithBodyInput(props: Props) {
const { botUser } = useChatContext();
const { botStudioEditProps, dateLocale } = useConstantState();

const { botUser, createdAt, bodyComponent, chainTop, chainBottom, messageFeedback, wideContainer = false } = props;
const { createdAt, bodyComponent, chainTop, chainBottom, messageFeedback, wideContainer = false } = props;

const profilePaddingBottom = (messageFeedback ? HEIGHTS.FEEDBACK : 0) + (wideContainer ? HEIGHTS.TIMESTAMP : 0);

Expand Down
2 changes: 0 additions & 2 deletions src/components/CurrentUserMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ const Root = styled.div<{ enableEmojiFeedback: boolean }>`
display: flex;
justify-content: flex-end;
align-items: end;
margin-bottom: 6px;
gap: 4px;
margin-top: ${({ enableEmojiFeedback }) => (enableEmojiFeedback ? '16px' : '0')};
`;

type Props = {
Expand Down
28 changes: 14 additions & 14 deletions src/components/CustomMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { User } from '@sendbird/chat';
import { BaseMessage } from '@sendbird/chat/message';

import { CoreMessageType, isVideoMessage } from '@uikit/utils';
import { isVideoMessage } from '@uikit/utils';

import AdminMessage from './AdminMessage';
import BotMessageFeedback from './BotMessageFeedback';
import BotMessageWithBodyInput from './BotMessageWithBodyInput';
import { useChatContext } from './chat/context/ChatProvider';
import CurrentUserMessage from './CurrentUserMessage';
import CustomMessageBody from './CustomMessageBody';
import CustomTypingIndicatorBubble from './CustomTypingIndicatorBubble';
Expand All @@ -21,26 +22,29 @@ import { messageExtension } from '../utils/messageExtension';
import { isSentBy } from '../utils/messages';

type Props = {
message: CoreMessageType;
message: BaseMessage;
activeSpinnerId: number;
botUser?: User;
chainTop?: boolean;
chainBottom?: boolean;
};

export default function CustomMessage(props: Props) {
const { message, activeSpinnerId, botUser } = props;
const { replacementTextList, enableEmojiFeedback, botStudioEditProps } = useConstantState();
const { botUser } = useChatContext();
const { message, activeSpinnerId } = props;
const { replacementTextList, enableEmojiFeedback, botStudioEditProps = {} } = useConstantState();
const { userId: currentUserId } = useWidgetSession();
const { profileUrl } = botStudioEditProps?.botInfo ?? {};
const { botInfo } = botStudioEditProps;

const botUserId = botUser?.userId;
const botProfileUrl = profileUrl ?? botUser?.profileUrl ?? '';
const botProfileUrl = botInfo?.profileUrl ?? botUser?.profileUrl ?? '';
const isWaitingForBotReply = activeSpinnerId === message.messageId && !!botUser;

const shouldRenderFeedback = () => {
return (
enableEmojiFeedback && message.myFeedbackStatus !== 'NOT_APPLICABLE' && !messageExtension.isStreaming(message)
enableEmojiFeedback &&
message.myFeedbackStatus !== 'NOT_APPLICABLE' &&
!messageExtension.isStreaming(message) &&
!messageExtension.isBotWelcomeMsg(message, botUserId ?? '')
);
};

Expand All @@ -65,7 +69,7 @@ export default function CustomMessage(props: Props) {
return (
<div>
<CurrentUserMessage message={message} />
{isWaitingForBotReply && <CustomTypingIndicatorBubble botProfileUrl={botProfileUrl} />}
{isWaitingForBotReply && <CustomTypingIndicatorBubble />}
</div>
);
}
Expand All @@ -77,7 +81,6 @@ export default function CustomMessage(props: Props) {
return (
<BotMessageWithBodyInput
{...props}
botUser={botUser}
bodyComponent={<FormMessage form={message.messageForm} message={message} />}
createdAt={message.createdAt}
/>
Expand All @@ -90,7 +93,6 @@ export default function CustomMessage(props: Props) {
<BotMessageWithBodyInput
wideContainer={isVideoMessage(message)}
{...props}
botUser={botUser}
bodyComponent={<FileMessage message={message} profileUrl={botProfileUrl} />}
createdAt={message.createdAt}
messageFeedback={renderFeedbackButtons()}
Expand All @@ -111,7 +113,6 @@ export default function CustomMessage(props: Props) {
<BotMessageWithBodyInput
wideContainer
{...props}
botUser={botUser}
bodyComponent={
<ShopItemsMessage message={message} streamingBody={<TypingBubble />} textBody={textMessageBody} />
}
Expand All @@ -125,7 +126,6 @@ export default function CustomMessage(props: Props) {
return (
<BotMessageWithBodyInput
{...props}
botUser={botUser}
bodyComponent={textMessageBody}
createdAt={message.createdAt}
messageFeedback={renderFeedbackButtons()}
Expand Down
12 changes: 10 additions & 2 deletions src/components/CustomTypingIndicatorBubble.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import BotProfileImage from './BotProfileImage';
import { useChatContext } from './chat/context/ChatProvider';
import { useConstantState } from '../context/ConstantContext';
import { TypingBubble } from '../foundation/components/TypingBubble';

function CustomTypingIndicatorBubble({ botProfileUrl }: { botProfileUrl: string }) {
function CustomTypingIndicatorBubble() {
const { botStudioEditProps = {} } = useConstantState();
const { botUser } = useChatContext();

const botInfo = botStudioEditProps.botInfo;
const botProfileUrl = botInfo?.profileUrl ?? botUser?.profileUrl;

return (
<div style={{ display: 'flex', alignItems: 'flex-end', gap: 8 }}>
<div style={{ display: 'flex', alignItems: 'flex-end', gap: 8, marginTop: 16 }}>
<BotProfileImage size={28} profileUrl={botProfileUrl} />
<TypingBubble />
</div>
Expand Down
12 changes: 7 additions & 5 deletions src/components/SuggestedRepliesContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ interface Props {
const SuggestedRepliesContainer = ({ replies = [], type = 'vertical', sendUserMessage }: Props) => {
if (replies.length <= 0) return null;
return (
<SuggestedReplies
replyOptions={replies}
onSendMessage={({ message }) => sendUserMessage?.({ message })}
type={type}
/>
<div style={{ marginTop: 8 }}>
<SuggestedReplies
replyOptions={replies}
onSendMessage={({ message }) => sendUserMessage?.({ message })}
type={type}
/>
</div>
);
};

Expand Down
1 change: 0 additions & 1 deletion src/components/UserMessageWithBodyInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { formatCreatedAtToAMPM } from '../utils/messageTimestamp';
const Root = styled.div`
display: flex;
align-items: flex-end;
margin-bottom: 6px;
flex-wrap: wrap;
gap: 8px;
position: relative;
Expand Down
13 changes: 11 additions & 2 deletions src/components/chat/context/ChatProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SendbirdChatWith, SendbirdError, SendbirdErrorCode } from '@sendbird/chat';
import { SendbirdChatWith, SendbirdError, SendbirdErrorCode, User } from '@sendbird/chat';
import { GroupChannel, GroupChannelModule } from '@sendbird/chat/groupChannel';
import { useGroupChannelMessages } from '@sendbird/uikit-tools';
import { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react';
Expand All @@ -18,6 +18,7 @@ export interface WidgetStringSet {
export interface ChatContextType {
sdk: SendbirdChatWith<[GroupChannelModule]> | null;
channel: GroupChannel | null;
botUser?: User;
dataSource: ReturnType<typeof useGroupChannelMessages>;
scrollSource: ReturnType<typeof useMessageListScroll>;

Expand Down Expand Up @@ -74,14 +75,22 @@ export const ChatContainer = (props: PropsWithChildren<ChatContainerProps>) => {
if (errorMessage) return <Placeholder type={'error'} label={errorMessage} />;

return (
<ChatProvider channel={channel} dataSource={dataSource} scrollSource={scrollSource} handlers={handlers} {...props}>
<ChatProvider
channel={channel}
botUser={channel?.members.find((it) => it.userId === botId)}
dataSource={dataSource}
scrollSource={scrollSource}
handlers={handlers}
{...props}
>
{children}
</ChatProvider>
);
};

interface ChatProviderProps extends ChatContainerProps {
channel: GroupChannel | null;
botUser?: User;
dataSource: ReturnType<typeof useGroupChannelMessages>;
scrollSource: ReturnType<typeof useMessageListScroll>;
handlers: WidgetChatHandlers;
Expand Down
7 changes: 3 additions & 4 deletions src/components/chat/hooks/useBotStudioView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ import { useChatContext } from '../context/ChatProvider';

export const useBotStudioView = () => {
const { botStudioEditProps = {}, botId, replacementTextList, stringSet } = useConstantState();
const { dataSource, channel, handlers } = useChatContext();
const { dataSource, handlers } = useChatContext();
const { suggestedRepliesDirection, welcomeMessages = [] } = botStudioEditProps;
const { messages } = dataSource;

const botUser = channel?.members.find((member) => member.userId === botId);
const originalWMs = getBotWelcomeMessages(messages, botId);

const firstUserMsg = messages[originalWMs.length + 1];
Expand Down Expand Up @@ -64,11 +63,10 @@ export const useBotStudioView = () => {
const isLastMessage = index === welcomeMessages.length - 1;

return (
<div key={index} style={{ padding: '0 16px' }}>
<div key={index} style={{ padding: '0 16px', marginBottom: 16 }}>
<BotMessageWithBodyInput
chainTop={index === 0}
chainBottom={index === welcomeMessages.length - 1}
botUser={botUser}
bodyComponent={<ParsedBotMessageBody text={text} tokens={tokens} />}
createdAt={firstOriginalWM?.createdAt}
/>
Expand Down Expand Up @@ -99,4 +97,5 @@ export const useBotStudioView = () => {

const dateSeparatorMargin = css`
margin: 8px 0;
padding: 0 16px;
`;
5 changes: 2 additions & 3 deletions src/components/chat/ui/ChatHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ type Props = {
fullscreen: boolean;
};
export const ChatHeader = ({ fullscreen }: Props) => {
const { botId, botStudioEditProps, isMobileView, enableWidgetExpandButton, betaMark, customBetaMarkText } =
const { botStudioEditProps, isMobileView, enableWidgetExpandButton, betaMark, customBetaMarkText } =
useConstantState();
const { sdk, channel, dataSource } = useChatContext();
const { sdk, channel, botUser, dataSource } = useChatContext();
const { setIsOpen } = useWidgetState();

const { botInfo } = botStudioEditProps ?? {};
const botUser = channel?.members.find((member) => member.userId === botId);
const botNickname = botInfo?.nickname ?? botUser?.nickname;
const profileUrl = botInfo?.profileUrl ?? botUser?.profileUrl;
const buttonSize = isMobileView ? 24 : 16;
Expand Down
6 changes: 2 additions & 4 deletions src/components/chat/ui/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,20 @@ import { useRef } from 'react';
import useSendbirdStateContext from '@uikit/hooks/useSendbirdStateContext';
import MessageInputWrapperView from '@uikit/modules/GroupChannel/components/MessageInputWrapper/MessageInputWrapperView';

import { useConstantState } from '../../../context/ConstantContext';
import { themedColors } from '../../../foundation/colors/css';
import { useBlockWhileBotResponding } from '../../../hooks/useBlockWhileBotResponding';
import { isIOSMobile } from '../../../utils';
import { useChatContext } from '../context/ChatProvider';

export const ChatInput = () => {
const { botId } = useConstantState();
const { channel, dataSource, handlers } = useChatContext();
const { channel, botUser, dataSource, handlers } = useChatContext();

const ref = useRef<HTMLDivElement>(null);

const { config } = useSendbirdStateContext();
const isMessageInputDisabled = useBlockWhileBotResponding({
lastMessage: dataSource.messages[dataSource.messages.length - 1],
botUser: channel?.members.find((it) => it.userId === botId),
botUser,
});

return (
Expand Down
Loading

0 comments on commit 1b3760f

Please sign in to comment.