Переглянути джерело

fix: stop response btn hide messages (#261)

Joel 1 рік тому
батько
коміт
5e772bd10b

+ 46 - 49
web/app/components/app/configuration/debug/index.tsx

@@ -1,36 +1,36 @@
 'use client'
 import type { FC } from 'react'
 import { useTranslation } from 'react-i18next'
-import React, { useEffect, useState, useRef } from 'react'
+import React, { useEffect, useRef, useState } from 'react'
 import cn from 'classnames'
 import produce from 'immer'
 import { useBoolean, useGetState } from 'ahooks'
 import { useContext } from 'use-context-selector'
+import dayjs from 'dayjs'
+import HasNotSetAPIKEY from '../base/warning-mask/has-not-set-api'
+import FormattingChanged from '../base/warning-mask/formatting-changed'
+import GroupName from '../base/group-name'
 import { AppType } from '@/types/app'
 import PromptValuePanel, { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel'
 import type { IChatItem } from '@/app/components/app/chat'
 import Chat from '@/app/components/app/chat'
 import ConfigContext from '@/context/debug-configuration'
 import { ToastContext } from '@/app/components/base/toast'
-import { sendChatMessage, sendCompletionMessage, fetchSuggestedQuestions, fetchConvesationMessages } from '@/service/debug'
+import { fetchConvesationMessages, fetchSuggestedQuestions, sendChatMessage, sendCompletionMessage } from '@/service/debug'
 import Button from '@/app/components/base/button'
 import type { ModelConfig as BackendModelConfig } from '@/types/app'
 import { promptVariablesToUserInputsForm } from '@/utils/model-config'
-import HasNotSetAPIKEY from '../base/warning-mask/has-not-set-api'
-import FormattingChanged from '../base/warning-mask/formatting-changed'
 import TextGeneration from '@/app/components/app/text-generate/item'
-import GroupName from '../base/group-name'
-import dayjs from 'dayjs'
 import { IS_CE_EDITION } from '@/config'
 
-interface IDebug {
+type IDebug = {
   hasSetAPIKEY: boolean
   onSetting: () => void
 }
 
 const Debug: FC<IDebug> = ({
   hasSetAPIKEY = true,
-  onSetting
+  onSetting,
 }) => {
   const { t } = useTranslation()
   const {
@@ -51,14 +51,12 @@ const Debug: FC<IDebug> = ({
     completionParams,
   } = useContext(ConfigContext)
 
-
   const [chatList, setChatList, getChatList] = useGetState<IChatItem[]>([])
   const chatListDomRef = useRef<HTMLDivElement>(null)
   useEffect(() => {
     // scroll to bottom
-    if (chatListDomRef.current) {
+    if (chatListDomRef.current)
       chatListDomRef.current.scrollTop = chatListDomRef.current.scrollHeight
-    }
   }, [chatList])
 
   const getIntroduction = () => replaceStringWithValues(introduction, modelConfig.configs.prompt_variables, inputs)
@@ -68,7 +66,7 @@ const Debug: FC<IDebug> = ({
         id: `${Date.now()}`,
         content: getIntroduction(),
         isAnswer: true,
-        isOpeningStatement: true
+        isOpeningStatement: true,
       }])
     }
   }, [introduction, modelConfig.configs.prompt_variables, inputs])
@@ -76,11 +74,12 @@ const Debug: FC<IDebug> = ({
   const [isResponsing, { setTrue: setResponsingTrue, setFalse: setResponsingFalse }] = useBoolean(false)
   const [abortController, setAbortController] = useState<AbortController | null>(null)
   const [isShowFormattingChangeConfirm, setIsShowFormattingChangeConfirm] = useState(false)
+  const [isShowSuggestion, setIsShowSuggestion] = useState(false)
 
   useEffect(() => {
-    if (formattingChanged && chatList.some(item => !item.isAnswer)) {
+    if (formattingChanged && chatList.some(item => !item.isAnswer))
       setIsShowFormattingChangeConfirm(true)
-    }
+
     setFormattingChanged(false)
   }, [formattingChanged])
 
@@ -88,12 +87,14 @@ const Debug: FC<IDebug> = ({
     setConversationId(null)
     abortController?.abort()
     setResponsingFalse()
-    setChatList(introduction ? [{
-      id: `${Date.now()}`,
-      content: getIntroduction(),
-      isAnswer: true,
-      isOpeningStatement: true
-    }] : [])
+    setChatList(introduction
+      ? [{
+        id: `${Date.now()}`,
+        content: getIntroduction(),
+        isAnswer: true,
+        isOpeningStatement: true,
+      }]
+      : [])
     setIsShowSuggestion(false)
   }
 
@@ -119,12 +120,11 @@ const Debug: FC<IDebug> = ({
     }) // compatible with old version
     // debugger
     requiredVars.forEach(({ key }) => {
-      if (hasEmptyInput) {
+      if (hasEmptyInput)
         return
-      }
-      if (!inputs[key]) {
+
+      if (!inputs[key])
         hasEmptyInput = true
-      }
     })
 
     if (hasEmptyInput) {
@@ -134,7 +134,6 @@ const Debug: FC<IDebug> = ({
     return !hasEmptyInput
   }
 
-  const [isShowSuggestion, setIsShowSuggestion] = useState(false)
   const doShowSuggestion = isShowSuggestion && !isResponsing
   const [suggestQuestions, setSuggestQuestions] = useState<string[]>([])
   const onSend = async (message: string) => {
@@ -147,7 +146,7 @@ const Debug: FC<IDebug> = ({
       dataset: {
         enabled: true,
         id,
-      }
+      },
     }))
 
     const postModelConfig: BackendModelConfig = {
@@ -155,17 +154,17 @@ const Debug: FC<IDebug> = ({
       user_input_form: promptVariablesToUserInputsForm(modelConfig.configs.prompt_variables),
       opening_statement: introduction,
       more_like_this: {
-        enabled: false
+        enabled: false,
       },
       suggested_questions_after_answer: suggestedQuestionsAfterAnswerConfig,
       agent_mode: {
         enabled: true,
-        tools: [...postDatasets]
+        tools: [...postDatasets],
       },
       model: {
         provider: modelConfig.provider,
         name: modelConfig.model_id,
-        completion_params: completionParams as any
+        completion_params: completionParams as any,
       },
     }
 
@@ -215,32 +214,32 @@ const Debug: FC<IDebug> = ({
           setConversationId(newConversationId)
           _newConversationId = newConversationId
         }
-        if (messageId) {
+        if (messageId)
           responseItem.id = messageId
-        }
+
         // closesure new list is outdated.
         const newListWithAnswer = produce(
           getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
           (draft) => {
-            if (!draft.find(item => item.id === questionId)) {
+            if (!draft.find(item => item.id === questionId))
               draft.push({ ...questionItem })
-            }
+
             draft.push({ ...responseItem })
           })
         setChatList(newListWithAnswer)
       },
       async onCompleted(hasError?: boolean) {
         setResponsingFalse()
-        if (hasError) {
+        if (hasError)
           return
-        }
+
         if (_newConversationId) {
           const { data }: any = await fetchConvesationMessages(appId, _newConversationId as string)
           const newResponseItem = data.find((item: any) => item.id === responseItem.id)
-          if (!newResponseItem) {
+          if (!newResponseItem)
             return
-          }
-          setChatList(produce(getChatList(), draft => {
+
+          setChatList(produce(getChatList(), (draft) => {
             const index = draft.findIndex(item => item.id === responseItem.id)
             if (index !== -1) {
               draft[index] = {
@@ -249,7 +248,7 @@ const Debug: FC<IDebug> = ({
                   time: dayjs.unix(newResponseItem.created_at).format('hh:mm A'),
                   tokens: newResponseItem.answer_tokens + newResponseItem.message_tokens,
                   latency: newResponseItem.provider_response_latency.toFixed(2),
-                }
+                },
               }
             }
           }))
@@ -263,10 +262,10 @@ const Debug: FC<IDebug> = ({
       onError() {
         setResponsingFalse()
         // role back placeholder answer
-        setChatList(produce(getChatList(), draft => {
+        setChatList(produce(getChatList(), (draft) => {
           draft.splice(draft.findIndex(item => item.id === placeholderAnswerId), 1)
         }))
-      }
+      },
     })
     return true
   }
@@ -277,7 +276,7 @@ const Debug: FC<IDebug> = ({
   }, [controlClearChatMessage])
 
   const [completionQuery, setCompletionQuery] = useState('')
-  const [completionRes, setCompletionRes] = useState(``)
+  const [completionRes, setCompletionRes] = useState('')
 
   const sendTextCompletion = async () => {
     if (isResponsing) {
@@ -297,7 +296,7 @@ const Debug: FC<IDebug> = ({
       dataset: {
         enabled: true,
         id,
-      }
+      },
     }))
 
     const postModelConfig: BackendModelConfig = {
@@ -308,16 +307,15 @@ const Debug: FC<IDebug> = ({
       more_like_this: moreLikeThisConifg,
       agent_mode: {
         enabled: true,
-        tools: [...postDatasets]
+        tools: [...postDatasets],
       },
       model: {
         provider: modelConfig.provider,
         name: modelConfig.model_id,
-        completion_params: completionParams as any
+        completion_params: completionParams as any,
       },
     }
 
-
     const data = {
       inputs,
       query: completionQuery,
@@ -338,11 +336,10 @@ const Debug: FC<IDebug> = ({
       },
       onError() {
         setResponsingFalse()
-      }
+      },
     })
   }
 
-
   return (
     <>
       <div className="shrink-0">
@@ -368,7 +365,7 @@ const Debug: FC<IDebug> = ({
         {/* Chat */}
         {mode === AppType.chat && (
           <div className="mt-[34px] h-full flex flex-col">
-            <div className={cn(doShowSuggestion ? 'pb-[140px]' : 'pb-[66px]', "relative mt-1.5 grow h-[200px] overflow-hidden")}>
+            <div className={cn(doShowSuggestion ? 'pb-[140px]' : (isResponsing ? 'pb-[113px]' : 'pb-[66px]'), 'relative mt-1.5 grow h-[200px] overflow-hidden')}>
               <div className="h-full overflow-y-auto" ref={chatListDomRef}>
                 {/* {JSON.stringify(chatList)} */}
                 <Chat

+ 73 - 71
web/app/components/share/chat/index.tsx

@@ -1,40 +1,39 @@
+/* eslint-disable @typescript-eslint/no-use-before-define */
 'use client'
 import type { FC } from 'react'
-import React, { useEffect, useState, useRef } from 'react'
+import React, { useEffect, useRef, useState } from 'react'
 import cn from 'classnames'
 import { useTranslation } from 'react-i18next'
 import { useContext } from 'use-context-selector'
 import produce from 'immer'
 import { useBoolean, useGetState } from 'ahooks'
+import AppUnavailable from '../../base/app-unavailable'
 import useConversation from './hooks/use-conversation'
+import s from './style.module.css'
 import { ToastContext } from '@/app/components/base/toast'
 import Sidebar from '@/app/components/share/chat/sidebar'
 import ConfigSence from '@/app/components/share/chat/config-scence'
 import Header from '@/app/components/share/header'
-import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, sendChatMessage, updateFeedback, fetchSuggestedQuestions } from '@/service/share'
+import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, sendChatMessage, updateFeedback } from '@/service/share'
 import type { ConversationItem, SiteInfo } from '@/models/share'
-import type { PromptConfig } from '@/models/debug'
+import type { PromptConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug'
 import type { Feedbacktype, IChatItem } from '@/app/components/app/chat'
 import Chat from '@/app/components/app/chat'
 import { changeLanguage } from '@/i18n/i18next-config'
 import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
 import Loading from '@/app/components/base/loading'
 import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel'
-import AppUnavailable from '../../base/app-unavailable'
 import { userInputsFormToPromptVariables } from '@/utils/model-config'
-import { SuggestedQuestionsAfterAnswerConfig } from '@/models/debug'
-import { InstalledApp } from '@/models/explore'
-
-import s from './style.module.css'
+import type { InstalledApp } from '@/models/explore'
 
 export type IMainProps = {
-  isInstalledApp?: boolean,
-  installedAppInfo? : InstalledApp
+  isInstalledApp?: boolean
+  installedAppInfo?: InstalledApp
 }
 
 const Main: FC<IMainProps> = ({
   isInstalledApp = false,
-  installedAppInfo
+  installedAppInfo,
 }) => {
   const { t } = useTranslation()
   const media = useBreakpoints()
@@ -53,7 +52,7 @@ const Main: FC<IMainProps> = ({
   const [plan, setPlan] = useState<string>('basic') // basic/plus/pro
   // in mobile, show sidebar by click button
   const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false)
-  // Can Use metadata(https://beta.nextjs.org/docs/api-reference/metadata) to set title. But it only works in server side client. 
+  // Can Use metadata(https://beta.nextjs.org/docs/api-reference/metadata) to set title. But it only works in server side client.
   useEffect(() => {
     if (siteInfo?.title) {
       if (plan !== 'basic')
@@ -61,7 +60,6 @@ const Main: FC<IMainProps> = ({
       else
         document.title = `${siteInfo.title} - Powered by Dify`
     }
-
   }, [siteInfo?.title, plan])
 
   /*
@@ -81,7 +79,7 @@ const Main: FC<IMainProps> = ({
     resetNewConversationInputs,
     setCurrInputs,
     setNewConversationInfo,
-    setExistConversationInfo
+    setExistConversationInfo,
   } = useConversation()
   const [hasMore, setHasMore] = useState<boolean>(false)
   const onMoreLoaded = ({ data: conversations, has_more }: any) => {
@@ -101,9 +99,9 @@ const Main: FC<IMainProps> = ({
     setChatList(generateNewChatListWithOpenstatement('', inputs))
   }
   const hasSetInputs = (() => {
-    if (!isNewConversation) {
+    if (!isNewConversation)
       return true
-    }
+
     return isChatStarted
   })()
 
@@ -111,7 +109,8 @@ const Main: FC<IMainProps> = ({
   const conversationIntroduction = currConversationInfo?.introduction || ''
 
   const handleConversationSwitch = () => {
-    if (!inited) return
+    if (!inited)
+      return
     if (!appId) {
       // wait for appId
       setTimeout(handleConversationSwitch, 100)
@@ -130,12 +129,13 @@ const Main: FC<IMainProps> = ({
         name: item?.name || '',
         introduction: notSyncToStateIntroduction,
       })
-    } else {
+    }
+    else {
       notSyncToStateInputs = newConversationInputs
       setCurrInputs(notSyncToStateInputs)
     }
 
-    // update chat list of current conversation 
+    // update chat list of current conversation
     if (!isNewConversation && !conversationIdChangeBecauseOfNew && !isResponsing) {
       fetchChatList(currConversationId, isInstalledApp, installedAppInfo?.id).then((res: any) => {
         const { data } = res
@@ -158,9 +158,8 @@ const Main: FC<IMainProps> = ({
       })
     }
 
-    if (isNewConversation && isChatStarted) {
+    if (isNewConversation && isChatStarted)
       setChatList(generateNewChatListWithOpenstatement())
-    }
 
     setControlFocus(Date.now())
   }
@@ -170,7 +169,8 @@ const Main: FC<IMainProps> = ({
     if (id === '-1') {
       createNewChat()
       setConversationIdChangeBecauseOfNew(true)
-    } else {
+    }
+    else {
       setConversationIdChangeBecauseOfNew(false)
     }
     // trigger handleConversationSwitch
@@ -186,9 +186,8 @@ const Main: FC<IMainProps> = ({
   const chatListDomRef = useRef<HTMLDivElement>(null)
   useEffect(() => {
     // scroll to bottom
-    if (chatListDomRef.current) {
+    if (chatListDomRef.current)
       chatListDomRef.current.scrollTop = chatListDomRef.current.scrollHeight
-    }
   }, [chatList, currConversationId])
   // user can not edit inputs if user had send message
   const canEditInpus = !chatList.some(item => item.isAnswer === false) && isNewConversation
@@ -196,15 +195,15 @@ const Main: FC<IMainProps> = ({
     // if new chat is already exist, do not create new chat
     abortController?.abort()
     setResponsingFalse()
-    if (conversationList.some(item => item.id === '-1')) {
+    if (conversationList.some(item => item.id === '-1'))
       return
-    }
-    setConversationList(produce(conversationList, draft => {
+
+    setConversationList(produce(conversationList, (draft) => {
       draft.unshift({
         id: '-1',
         name: t('share.chat.newChatDefaultName'),
         inputs: newConversationInputs,
-        introduction: conversationIntroduction
+        introduction: conversationIntroduction,
       })
     }))
   }
@@ -213,36 +212,37 @@ const Main: FC<IMainProps> = ({
   const generateNewChatListWithOpenstatement = (introduction?: string, inputs?: Record<string, any> | null) => {
     let caculatedIntroduction = introduction || conversationIntroduction || ''
     const caculatedPromptVariables = inputs || currInputs || null
-    if (caculatedIntroduction && caculatedPromptVariables) {
+    if (caculatedIntroduction && caculatedPromptVariables)
       caculatedIntroduction = replaceStringWithValues(caculatedIntroduction, promptConfig?.prompt_variables || [], caculatedPromptVariables)
-    }
+
     // console.log(isPublicVersion)
     const openstatement = {
       id: `${Date.now()}`,
       content: caculatedIntroduction,
       isAnswer: true,
       feedbackDisabled: true,
-      isOpeningStatement: isPublicVersion
+      isOpeningStatement: isPublicVersion,
     }
-    if (caculatedIntroduction) {
+    if (caculatedIntroduction)
       return [openstatement]
-    }
+
     return []
   }
 
   const fetchInitData = () => {
-    return Promise.all([isInstalledApp ? {
-      app_id: installedAppInfo?.id, 
-      site: {
-        title: installedAppInfo?.app.name,
-        prompt_public: false,
-        copyright: ''
-      },
-      plan: 'basic',
-    }: fetchAppInfo(), fetchConversations(isInstalledApp, installedAppInfo?.id), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
+    return Promise.all([isInstalledApp
+      ? {
+        app_id: installedAppInfo?.id,
+        site: {
+          title: installedAppInfo?.app.name,
+          prompt_public: false,
+          copyright: '',
+        },
+        plan: 'basic',
+      }
+      : fetchAppInfo(), fetchConversations(isInstalledApp, installedAppInfo?.id), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
   }
 
-
   // init
   useEffect(() => {
     (async () => {
@@ -255,16 +255,16 @@ const Main: FC<IMainProps> = ({
         setIsPublicVersion(tempIsPublicVersion)
         const prompt_template = ''
         // handle current conversation id
-        const { data: conversations, has_more } = conversationData as { data: ConversationItem[], has_more: boolean }
+        const { data: conversations, has_more } = conversationData as { data: ConversationItem[]; has_more: boolean }
         const _conversationId = getConversationIdFromStorage(appId)
         const isNotNewConversation = conversations.some(item => item.id === _conversationId)
         setHasMore(has_more)
         // fetch new conversation info
         const { user_input_form, opening_statement: introduction, suggested_questions_after_answer }: any = appParams
         const prompt_variables = userInputsFormToPromptVariables(user_input_form)
-        if(siteInfo.default_language) {
+        if (siteInfo.default_language)
           changeLanguage(siteInfo.default_language)
-        }
+
         setNewConversationInfo({
           name: t('share.chat.newChatDefaultName'),
           introduction,
@@ -272,20 +272,22 @@ const Main: FC<IMainProps> = ({
         setSiteInfo(siteInfo as SiteInfo)
         setPromptConfig({
           prompt_template,
-          prompt_variables: prompt_variables,
+          prompt_variables,
         } as PromptConfig)
         setSuggestedQuestionsAfterAnswerConfig(suggested_questions_after_answer)
 
         setConversationList(conversations as ConversationItem[])
 
-        if (isNotNewConversation) {
+        if (isNotNewConversation)
           setCurrConversationId(_conversationId, appId, false)
-        }
+
         setInited(true)
-      } catch (e: any) {
+      }
+      catch (e: any) {
         if (e.status === 404) {
           setAppUnavailable(true)
-        } else {
+        }
+        else {
           setIsUnknwonReason(true)
           setAppUnavailable(true)
         }
@@ -303,21 +305,20 @@ const Main: FC<IMainProps> = ({
   const checkCanSend = () => {
     const prompt_variables = promptConfig?.prompt_variables
     const inputs = currInputs
-    if (!inputs || !prompt_variables || prompt_variables?.length === 0) {
+    if (!inputs || !prompt_variables || prompt_variables?.length === 0)
       return true
-    }
+
     let hasEmptyInput = false
     const requiredVars = prompt_variables?.filter(({ key, name, required }) => {
       const res = (!key || !key.trim()) || (!name || !name.trim()) || (required || required === undefined || required === null)
       return res
     }) || [] // compatible with old version
     requiredVars.forEach(({ key }) => {
-      if (hasEmptyInput) {
+      if (hasEmptyInput)
         return
-      }
-      if (!inputs?.[key]) {
+
+      if (!inputs?.[key])
         hasEmptyInput = true
-      }
     })
 
     if (hasEmptyInput) {
@@ -378,9 +379,8 @@ const Main: FC<IMainProps> = ({
       onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId }: any) => {
         responseItem.content = responseItem.content + message
         responseItem.id = messageId
-        if (isFirstMessage && newConversationId) {
+        if (isFirstMessage && newConversationId)
           tempNewConversationId = newConversationId
-        }
 
         // closesure new list is outdated.
         const newListWithAnswer = produce(
@@ -395,9 +395,9 @@ const Main: FC<IMainProps> = ({
       },
       async onCompleted(hasError?: boolean) {
         setResponsingFalse()
-        if (hasError) {
+        if (hasError)
           return
-        }
+
         let currChatList = conversationList
         if (getConversationIdChangeBecauseOfNew()) {
           const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppInfo?.id)
@@ -418,7 +418,7 @@ const Main: FC<IMainProps> = ({
       onError() {
         setResponsingFalse()
         // role back placeholder answer
-        setChatList(produce(getChatList(), draft => {
+        setChatList(produce(getChatList(), (draft) => {
           draft.splice(draft.findIndex(item => item.id === placeholderAnswerId), 1)
         }))
       },
@@ -476,18 +476,20 @@ const Main: FC<IMainProps> = ({
           onCreateNewChat={() => handleConversationIdChange('-1')}
         />
       )}
-      
+
       {/* {isNewConversation ? 'new' : 'exist'}
         {JSON.stringify(newConversationInputs ? newConversationInputs : {})}
         {JSON.stringify(existConversationInputs ? existConversationInputs : {})} */}
-      <div 
+      <div
         className={cn(
-          "flex rounded-t-2xl bg-white overflow-hidden",
+          'flex rounded-t-2xl bg-white overflow-hidden',
           isInstalledApp && 'rounded-b-2xl',
         )}
-        style={isInstalledApp ? {
-          boxShadow: '0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03)'
-        } : {}}
+        style={isInstalledApp
+          ? {
+            boxShadow: '0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03)',
+          }
+          : {}}
       >
         {/* sidebar */}
         {!isMobile && renderSidebar()}
@@ -504,8 +506,8 @@ const Main: FC<IMainProps> = ({
         {/* main */}
         <div className={cn(
           isInstalledApp ? s.installedApp : 'h-[calc(100vh_-_3rem)]',
-          'flex-grow flex flex-col overflow-y-auto'
-          )
+          'flex-grow flex flex-col overflow-y-auto',
+        )
         }>
           <ConfigSence
             conversationName={conversationName}
@@ -522,7 +524,7 @@ const Main: FC<IMainProps> = ({
 
           {
             hasSetInputs && (
-              <div className={cn(doShowSuggestion ? 'pb-[140px]' : 'pb-[66px]', 'relative grow h-[200px] pc:w-[794px] max-w-full mobile:w-full mx-auto mb-3.5 overflow-hidden')}>
+              <div className={cn(doShowSuggestion ? 'pb-[140px]' : (isResponsing ? 'pb-[113px]' : 'pb-[66px]'), 'relative grow h-[200px] pc:w-[794px] max-w-full mobile:w-full mx-auto mb-3.5 overflow-hidden')}>
                 <div className='h-full overflow-y-auto' ref={chatListDomRef}>
                   <Chat
                     chatList={chatList}