1
1
import { useParams } from 'react-router-dom'
2
2
import useCourse from '../../hooks/useCourse'
3
3
import useUserStatus from '../../hooks/useUserStatus'
4
- import { useRef , useState } from 'react'
4
+ import { useRef , useState , useContext , useEffect } from 'react'
5
5
import useLocalStorageState from '../../hooks/useLocalStorageState'
6
6
import { DEFAULT_MODEL } from '../../../config'
7
7
import useInfoTexts from '../../hooks/useInfoTexts'
@@ -15,6 +15,7 @@ import { Conversation } from './Conversation'
15
15
import { ChatBox } from './ChatBox'
16
16
import { getCompletionStream } from './util'
17
17
import { SystemPrompt } from './System'
18
+ import { AppContext } from '../../util/context'
18
19
19
20
export const ChatV2 = ( ) => {
20
21
const { courseId } = useParams ( )
@@ -29,6 +30,10 @@ export const ChatV2 = () => {
29
30
const [ system , setSystem ] = useLocalStorageState < { content : string } > ( 'general-chat-system' , { content : '' } )
30
31
const [ message , setMessage ] = useLocalStorageState < { content : string } > ( 'general-chat-current' , { content : '' } )
31
32
const [ messages , setMessages ] = useLocalStorageState < Message [ ] > ( 'general-chat-messages' , [ ] )
33
+
34
+ const appContainerRef = useContext ( AppContext )
35
+ const chatContainerRef = useRef < HTMLDivElement > ( null )
36
+
32
37
const inputFileRef = useRef < HTMLInputElement > ( null )
33
38
const [ fileName , setFileName ] = useState < string > ( '' )
34
39
const [ completion , setCompletion ] = useState ( '' )
@@ -130,6 +135,28 @@ export const ChatV2 = () => {
130
135
clearRetryTimeout ( )
131
136
}
132
137
138
+ useEffect ( ( ) => {
139
+ const chatContainer = chatContainerRef . current
140
+ const appContainer = appContainerRef . current
141
+
142
+ if ( ! chatContainer || ! appContainer || ! messages . length ) return
143
+
144
+ const scrollToBottom = ( ) => {
145
+ appContainer . scrollIntoView ( {
146
+ behavior : 'smooth' ,
147
+ block : 'end' ,
148
+ } )
149
+ }
150
+
151
+ const resizeObserver = new ResizeObserver ( ( ) => {
152
+ scrollToBottom ( )
153
+ } )
154
+
155
+ resizeObserver . observe ( chatContainer )
156
+
157
+ return ( ) => resizeObserver . disconnect ( )
158
+ } , [ ] )
159
+
133
160
return (
134
161
< Box
135
162
sx = { {
@@ -138,26 +165,23 @@ export const ChatV2 = () => {
138
165
flexDirection : 'column' ,
139
166
} }
140
167
>
141
- < Box
142
- sx = { {
143
- display : 'flex' ,
144
- gap : '1rem' ,
145
- } }
146
- >
168
+ < Box sx = { { display : 'flex' , gap : '1rem' } } >
147
169
{ disclaimerInfo && < Disclaimer disclaimer = { disclaimerInfo } /> }
148
170
< SystemPrompt content = { system . content } setContent = { ( content ) => setSystem ( { content } ) } />
149
171
< Button onClick = { handleReset } > Reset</ Button >
150
172
</ Box >
151
- < Conversation messages = { messages } completion = { completion } />
152
- < ChatBox
153
- disabled = { false }
154
- onSubmit = { ( message ) => {
155
- if ( message . trim ( ) ) {
156
- handleSubmit ( message )
157
- setMessage ( { content : '' } )
158
- }
159
- } }
160
- />
173
+ < Box ref = { chatContainerRef } >
174
+ < Conversation messages = { messages } completion = { completion } />
175
+ < ChatBox
176
+ disabled = { false }
177
+ onSubmit = { ( message ) => {
178
+ if ( message . trim ( ) ) {
179
+ handleSubmit ( message )
180
+ setMessage ( { content : '' } )
181
+ }
182
+ } }
183
+ />
184
+ </ Box >
161
185
</ Box >
162
186
)
163
187
}
0 commit comments