diff --git a/packages/chat/src/chat-bubble/chat-bubble.tsx b/packages/chat/src/chat-bubble/chat-bubble.tsx index 8971a30277..d3ac51a7d7 100644 --- a/packages/chat/src/chat-bubble/chat-bubble.tsx +++ b/packages/chat/src/chat-bubble/chat-bubble.tsx @@ -22,8 +22,8 @@ interface ChatBubbleProps { displayTarget: UserType postMessageAction?: PostMessageActionType disableUnreadCount?: boolean - onRetryButtonClick?: () => void - onRetryCancelButtonClick?: () => void + onRetryButtonClick?: (message: MessageInterface) => void + onRetryCancelButtonClick?: (message: MessageInterface) => void blindedText?: string bubbleColor?: ChatBubbleColor } @@ -79,7 +79,7 @@ const ChatBubble = ({ !!postMessageAction const onRetry = () => { - onRetryButtonClick?.() + onRetryButtonClick?.(message) return postMessageAction?.( message.payload as TextPayload | ImagePayload, true, @@ -87,7 +87,7 @@ const ChatBubble = ({ } const onCancel = () => { - onRetryCancelButtonClick?.() + onRetryCancelButtonClick?.(message) } return ( diff --git a/packages/chat/src/chat/chat-container.tsx b/packages/chat/src/chat/chat-container.tsx index 44b39e806e..d435a3526c 100644 --- a/packages/chat/src/chat/chat-container.tsx +++ b/packages/chat/src/chat/chat-container.tsx @@ -17,7 +17,7 @@ const ScrollProvider = dynamic(() => import('./scroll-context'), { export interface ChatContainerProps extends ChatContextValue { /** - * Chat list와 보내기 Input 창을 감싸는 컨테이너로, 커스텀 스타일 등 적용 가능 + * Chat list를 감싸는 컨테이너로, 커스텀 스타일 등 적용 가능 */ container: ElementType /** diff --git a/packages/chat/src/chat/chat.tsx b/packages/chat/src/chat/chat.tsx index ef354c2de7..b4a3216ebe 100644 --- a/packages/chat/src/chat/chat.tsx +++ b/packages/chat/src/chat/chat.tsx @@ -92,6 +92,7 @@ export const Chat = ({ const [ { messages, + failedMessages, hasPrevMessage, otherUnreadInfo, lastMessageId, @@ -202,7 +203,6 @@ export const Chat = ({ dispatch({ action: ChatActions.POST, messages: newMessages, - payload, }) const lastMessage = newMessages[newMessages.length - 1] @@ -211,7 +211,7 @@ export const Chat = ({ dispatch({ action: ChatActions.FAILED_TO_POST, message: { - id: NaN, + id: new Date().getTime(), roomId: room.id, senderId: userInfo.me.id, payload, @@ -262,34 +262,73 @@ export const Chat = ({ } } + function removeFromFailedMessages(message: MessageInterface) { + dispatch({ + action: ChatActions.REMOVE_FROM_FAILED, + message, + }) + } + + function onRetry(message: MessageInterface) { + removeFromFailedMessages(message) + onRetryButtonClick?.() + } + + function onRetryCancel(message: MessageInterface) { + removeFromFailedMessages(message) + onRetryButtonClick?.() + } + return ( <> - + {userInfo ? ( + <> + + + + ) : null} diff --git a/packages/chat/src/chat/reducer.ts b/packages/chat/src/chat/reducer.ts index 14122d0b73..d0354fb10f 100644 --- a/packages/chat/src/chat/reducer.ts +++ b/packages/chat/src/chat/reducer.ts @@ -1,9 +1,4 @@ -import { - MessageInterface, - OtherUnreadInterface, - TextPayload, - ImagePayload, -} from '../types' +import { MessageInterface, OtherUnreadInterface } from '../types' export enum ChatActions { INIT, // 최초에 메시지 @@ -12,10 +7,12 @@ export enum ChatActions { POST, // 메시지 전송 FAILED_TO_POST, // 메시지 전송 실패 UPDATE, // 읽음 표시 업데이트 + REMOVE_FROM_FAILED, // 전송 실패 메세지 재전송 또는 삭제 } export interface ChatState { messages: MessageInterface[] + failedMessages: MessageInterface[] hasPrevMessage: boolean otherUnreadInfo: OtherUnreadInterface[] firstMessageId: number | null @@ -39,7 +36,6 @@ export type ChatAction = | { action: ChatActions.POST messages: MessageInterface[] - payload: TextPayload | ImagePayload } | { action: ChatActions.FAILED_TO_POST @@ -49,6 +45,7 @@ export type ChatAction = action: ChatActions.UPDATE otherUnreadInfo: OtherUnreadInterface[] } + | { action: ChatActions.REMOVE_FROM_FAILED; message: MessageInterface } export const ChatReducer = ( state: ChatState, @@ -81,15 +78,7 @@ export const ChatReducer = ( case ChatActions.POST: return { ...state, - messages: mergeMessages( - state.messages.some((message) => !message.id) - ? state.messages.filter( - (message) => - !message.id && !Object.is(message.payload, action.payload), - ) - : state.messages, - action.messages, - ), + messages: mergeMessages(state.messages, action.messages), lastMessageId: Number(action.messages[action.messages.length - 1].id), } @@ -103,7 +92,7 @@ export const ChatReducer = ( case ChatActions.FAILED_TO_POST: return { ...state, - messages: [...state.messages, action.message], + failedMessages: [...state.failedMessages, action.message], } case ChatActions.UPDATE: @@ -112,6 +101,14 @@ export const ChatReducer = ( otherUnreadInfo: action.otherUnreadInfo, } + case ChatActions.REMOVE_FROM_FAILED: + return { + ...state, + failedMessages: state.failedMessages.filter( + (message) => message.id !== action.message.id, + ), + } + default: throw new Error('unexpected action') } @@ -119,6 +116,7 @@ export const ChatReducer = ( export const initialChatState: ChatState = { messages: [], + failedMessages: [], hasPrevMessage: true, otherUnreadInfo: [], firstMessageId: null, diff --git a/packages/chat/src/types/index.ts b/packages/chat/src/types/index.ts index 36c896b05f..f4fcff0784 100644 --- a/packages/chat/src/types/index.ts +++ b/packages/chat/src/types/index.ts @@ -43,7 +43,7 @@ export interface RoomListResultWithPagingInterface export interface RoomMetadata { name: string memberCounts: number - faqId?: string + articleId?: string } export interface RoomInterface { @@ -56,7 +56,7 @@ export interface RoomInterface { members: UserInterface[] isDirect: boolean createdAt: string - metadata: RoomMetadata + metadata?: RoomMetadata } export type DisplayTargetAll = 'all'