1+ import { useRef , useState } from 'react'
2+
13import {
24 EngineManager ,
35 ErrorCode ,
79
810import { useAtomValue , useSetAtom } from 'jotai'
911
12+ import { CheckIcon , ClipboardIcon , SearchCodeIcon } from 'lucide-react'
13+
1014import AutoLink from '@/containers/AutoLink'
1115import ModalTroubleShooting , {
1216 modalTroubleShootingAtom ,
@@ -24,30 +28,25 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
2428 const setMainState = useSetAtom ( mainViewStateAtom )
2529 const setSelectedSettingScreen = useSetAtom ( selectedSettingAtom )
2630 const activeAssistant = useAtomValue ( activeAssistantAtom )
27-
28- const defaultDesc = ( ) => {
29- return (
30- < >
31- < p >
32- { `Something's wrong.` } Access
33- < span
34- className = "cursor-pointer text-[hsla(var(--app-link))] underline"
35- onClick = { ( ) => setModalTroubleShooting ( true ) }
36- >
37- troubleshooting assistance
38- </ span >
39- now.
40- </ p >
41- < ModalTroubleShooting />
42- </ >
43- )
44- }
31+ const errorDivRef = useRef < HTMLDivElement > ( null )
32+ const [ copied , setCopied ] = useState ( false )
4533
4634 const getEngine = ( ) => {
4735 const engineName = activeAssistant ?. model ?. engine
4836 return engineName ? EngineManager . instance ( ) . get ( engineName ) : null
4937 }
5038
39+ const handleCopy = ( ) => {
40+ if ( errorDivRef . current ) {
41+ const errorText = errorDivRef . current . innerText
42+ if ( errorText ) {
43+ navigator . clipboard . writeText ( errorText )
44+ setCopied ( true )
45+ setTimeout ( ( ) => setCopied ( false ) , 2000 )
46+ }
47+ }
48+ }
49+
5150 const getErrorTitle = ( ) => {
5251 const engine = getEngine ( )
5352
@@ -69,9 +68,9 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
6968 </ button > { ' ' }
7069 and try again.
7170 </ span >
72- { defaultDesc ( ) }
7371 </ >
7472 )
73+
7574 default :
7675 return (
7776 < p
@@ -90,7 +89,6 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
9089 { message ?. content [ 0 ] ?. text ?. value && (
9190 < AutoLink text = { message ?. content [ 0 ] ?. text ?. value } />
9291 ) }
93- { defaultDesc ( ) }
9492 </ >
9593 ) }
9694 </ p >
@@ -99,15 +97,54 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
9997 }
10098
10199 return (
102- < div className = "mx-auto my-6 max-w-[700px]" >
103- { ! ! message . metadata ?. error && (
104- < div
105- key = { message . id }
106- className = "mx-6 flex flex-col items-center space-y-2 text-center font-medium text-[hsla(var(--text-secondary))]"
107- >
108- { getErrorTitle ( ) }
100+ < div className = "mx-auto my-6 max-w-[700px] px-4" >
101+ < div
102+ className = "mx-auto max-w-[400px] rounded-lg border border-[hsla(var(--app-border))]"
103+ key = { message . id }
104+ >
105+ < div className = "flex justify-between border-b border-inherit px-4 py-2" >
106+ < h6 className = "text-[hsla(var(--destructive-bg))]" > Error</ h6 >
107+ < div className = "flex gap-x-4 text-xs" >
108+ < div >
109+ < span
110+ className = "flex cursor-pointer items-center gap-x-1 text-[hsla(var(--app-link))]"
111+ onClick = { ( ) => setModalTroubleShooting ( true ) }
112+ >
113+ < SearchCodeIcon size = { 14 } className = "text-inherit" />
114+ Troubleshooting
115+ </ span >
116+ < ModalTroubleShooting />
117+ </ div >
118+ < div
119+ className = "flex cursor-pointer items-center gap-x-1 text-[hsla(var(--text-secondary))]"
120+ onClick = { handleCopy }
121+ >
122+ { copied ? (
123+ < >
124+ < CheckIcon
125+ size = { 14 }
126+ className = "text-[hsla(var(--success-bg))]"
127+ />
128+ Copied
129+ </ >
130+ ) : (
131+ < >
132+ < ClipboardIcon size = { 14 } className = "text-inherit" />
133+ Copy
134+ </ >
135+ ) }
136+ </ div >
137+ </ div >
138+ </ div >
139+ < div className = "max-h-[80px] w-full overflow-x-auto p-4 py-2" >
140+ < div
141+ className = "text-xs leading-relaxed text-[hsla(var(--text-secondary))]"
142+ ref = { errorDivRef }
143+ >
144+ { getErrorTitle ( ) }
145+ </ div >
109146 </ div >
110- ) }
147+ </ div >
111148 </ div >
112149 )
113150}
0 commit comments