@@ -9,10 +9,13 @@ import useSWR from "swr";
99import { getQuestionExample } from "../actions/questionExample" ;
1010import { getLanguageName } from "../pagesList" ;
1111import { ReplCommand , ReplOutput } from "../terminal/repl" ;
12+ import { MarkdownSection } from "./splitMarkdown" ;
1213
1314interface ChatFormProps {
14- documentContent : string ;
15- sectionId : string ;
15+ docs_id : string ;
16+ splitMdContent : MarkdownSection [ ] ;
17+ sectionInView : boolean [ ] ;
18+ onClose : ( ) => void ;
1619 replOutputs : ReplCommand [ ] ;
1720 fileContents : Array < {
1821 name : string ;
@@ -22,21 +25,30 @@ interface ChatFormProps {
2225}
2326
2427export function ChatForm ( {
25- documentContent,
26- sectionId,
28+ docs_id,
29+ splitMdContent,
30+ sectionInView,
31+ onClose,
2732 replOutputs,
2833 fileContents,
2934 execResults,
3035} : ChatFormProps ) {
31- const [ messages , updateChatHistory ] = useChatHistory ( sectionId ) ;
36+ // const [messages, updateChatHistory] = useChatHistory(sectionId);
3237 const [ inputValue , setInputValue ] = useState ( "" ) ;
3338 const [ isLoading , setIsLoading ] = useState ( false ) ;
34- const [ isFormVisible , setIsFormVisible ] = useState ( false ) ;
3539
36- const lang = getLanguageName ( sectionId ) ;
40+ const lang = getLanguageName ( docs_id ) ;
41+
42+ const documentContentInView = splitMdContent
43+ . filter ( ( _ , index ) => sectionInView [ index ] )
44+ . map (
45+ ( section ) =>
46+ `${ "#" . repeat ( section . level ) } ${ section . title } \n${ section . content } `
47+ )
48+ . join ( "\n\n" ) ;
3749 const { data : exampleData , error : exampleError } = useSWR (
3850 // 質問フォームを開いたときだけで良い
39- isFormVisible ? { lang, documentContent } : null ,
51+ { lang, documentContentInView } ,
4052 getQuestionExample ,
4153 {
4254 // リクエストは古くても構わないので1回でいい
@@ -91,126 +103,65 @@ export function ChatForm({
91103 setIsLoading ( false ) ;
92104 } ;
93105
94- const handleClearHistory = ( ) => {
95- updateChatHistory ( [ ] ) ;
96- } ;
97-
98106 return (
99- < >
100- { isFormVisible && (
101- < form
102- className = "border border-2 border-secondary shadow-md rounded-lg bg-base-100"
107+ < form
108+ className = "border border-2 border-secondary shadow-lg rounded-lg bg-base-100"
109+ style = { {
110+ width : "100%" ,
111+ textAlign : "center" ,
112+ boxShadow : "-moz-initial" ,
113+ } }
114+ onSubmit = { handleSubmit }
115+ >
116+ < div className = "input-area" >
117+ < textarea
118+ className = "textarea textarea-ghost textarea-md rounded-lg"
119+ placeholder = {
120+ "質問を入力してください" +
121+ ( exampleData
122+ ? ` (例:「${ exampleData [ Math . floor ( exampleChoice * exampleData . length ) ] } 」)`
123+ : "" )
124+ }
103125 style = { {
104126 width : "100%" ,
105- textAlign : "center" ,
106- boxShadow : "-moz-initial" ,
127+ height : "110px" ,
128+ resize : "none" ,
129+ outlineStyle : "none" ,
107130 } }
108- onSubmit = { handleSubmit }
109- >
110- < div className = "input-area" >
111- < textarea
112- className = "textarea textarea-ghost textarea-md rounded-lg"
113- placeholder = {
114- "質問を入力してください" +
115- ( exampleData
116- ? ` (例:「${ exampleData [ Math . floor ( exampleChoice * exampleData . length ) ] } 」)`
117- : "" )
118- }
119- style = { {
120- width : "100%" ,
121- height : "110px" ,
122- resize : "none" ,
123- outlineStyle : "none" ,
124- } }
125- value = { inputValue }
126- onChange = { ( e ) => setInputValue ( e . target . value ) }
127- disabled = { isLoading }
128- > </ textarea >
129- </ div >
130- < div
131- className = "controls"
132- style = { {
133- margin : "10px" ,
134- display : "flex" ,
135- alignItems : "center" ,
136- justifyContent : "space-between" ,
137- } }
131+ value = { inputValue }
132+ onChange = { ( e ) => setInputValue ( e . target . value ) }
133+ disabled = { isLoading }
134+ > </ textarea >
135+ </ div >
136+ < div
137+ className = "controls"
138+ style = { {
139+ margin : "10px" ,
140+ display : "flex" ,
141+ alignItems : "center" ,
142+ justifyContent : "space-between" ,
143+ } }
144+ >
145+ < div className = "left-icons" >
146+ < button
147+ className = "btn btn-soft btn-secondary rounded-full"
148+ onClick = { onClose }
149+ type = "button"
138150 >
139- < div className = "left-icons" >
140- < button
141- className = "btn btn-soft btn-secondary rounded-full"
142- onClick = { ( ) => setIsFormVisible ( false ) }
143- type = "button"
144- >
145- 閉じる
146- </ button >
147- </ div >
148- < div className = "right-controls" >
149- < button
150- type = "submit"
151- className = "btn btn-soft btn-circle btn-accent border-2 border-accent rounded-full"
152- title = "送信"
153- disabled = { isLoading }
154- >
155- < span className = "icon" > ➤</ span >
156- </ button >
157- </ div >
158- </ div >
159- </ form >
160- ) }
161- { ! isFormVisible && (
162- < button
163- className = "btn btn-soft btn-secondary rounded-full"
164- onClick = { ( ) => {
165- setIsFormVisible ( true ) ;
166- setExampleChoice ( Math . random ( ) ) ;
167- } }
168- >
169- チャットを開く
170- </ button >
171- ) }
172-
173- { messages . length > 0 && (
174- < article className = "mt-4" >
175- < div className = "flex justify-between items-center mb-2" >
176- < h3 className = "text-lg font-semibold" > AIとのチャット</ h3 >
177- < button
178- onClick = { handleClearHistory }
179- className = "btn btn-ghost btn-sm text-xs"
180- aria-label = "チャット履歴を削除"
181- >
182- 履歴を削除
183- </ button >
184- </ div >
185- { messages . map ( ( msg , index ) => (
186- < div
187- key = { index }
188- className = { `chat ${ msg . sender === "user" ? "chat-end" : "chat-start" } ` }
189- >
190- < div
191- className = { clsx (
192- "chat-bubble" ,
193- { "bg-primary text-primary-content" : msg . sender === "user" } ,
194- {
195- "bg-secondary-content dark:bg-neutral text-black dark:text-white" :
196- msg . sender === "ai" && ! msg . isError ,
197- } ,
198- { "chat-bubble-error" : msg . isError }
199- ) }
200- style = { { maxWidth : "100%" , wordBreak : "break-word" } }
201- >
202- < StyledMarkdown content = { msg . text } />
203- </ div >
204- </ div >
205- ) ) }
206- </ article >
207- ) }
208-
209- { isLoading && (
210- < div className = "mt-2 text-l text-gray-500 animate-pulse" >
211- AIが考え中です…
151+ 閉じる
152+ </ button >
153+ </ div >
154+ < div className = "right-controls" >
155+ < button
156+ type = "submit"
157+ className = "btn btn-soft btn-circle btn-accent border-2 border-accent rounded-full"
158+ title = "送信"
159+ disabled = { isLoading }
160+ >
161+ < span className = "icon" > ➤</ span >
162+ </ button >
212163 </ div >
213- ) }
214- </ >
164+ </ div >
165+ </ form >
215166 ) ;
216167}
0 commit comments