66 getSession ,
77 deleteSession ,
88} from '../../services/local-session.mjs'
9- import { useEffect , useRef , useState } from 'react'
9+ import { useEffect , useRef , useState , useMemo } from 'react'
1010import './styles.scss'
1111import { useConfig } from '../../hooks/use-config.mjs'
1212import { useTranslation } from 'react-i18next'
@@ -25,6 +25,7 @@ function App() {
2525 const [ sessionId , setSessionId ] = useState ( null )
2626 const [ currentSession , setCurrentSession ] = useState ( null )
2727 const [ renderContent , setRenderContent ] = useState ( false )
28+ const [ searchQuery , setSearchQuery ] = useState ( '' )
2829 const currentPort = useRef ( null )
2930
3031 const setSessionIdSafe = async ( sessionId ) => {
@@ -103,6 +104,30 @@ function App() {
103104 await setSessionIdSafe ( sessions [ 0 ] . sessionId )
104105 }
105106
107+ // Filter sessions based on search query (memoized for performance)
108+ const filteredSessions = useMemo ( ( ) => {
109+ const query = searchQuery . trim ( ) . toLowerCase ( )
110+ if ( ! query ) return sessions
111+
112+ return sessions . filter ( ( session ) => {
113+ // Search in session name
114+ if ( session . sessionName && session . sessionName . toLowerCase ( ) . includes ( query ) ) {
115+ return true
116+ }
117+
118+ // Search in conversation records
119+ if ( session . conversationRecords ) {
120+ return session . conversationRecords . some ( ( record ) => {
121+ const questionMatch = record . question && record . question . toLowerCase ( ) . includes ( query )
122+ const answerMatch = record . answer && record . answer . toLowerCase ( ) . includes ( query )
123+ return questionMatch || answerMatch
124+ } )
125+ }
126+
127+ return false
128+ } )
129+ } , [ sessions , searchQuery ] )
130+
106131 return (
107132 < div className = "IndependentPanel" >
108133 < div className = "chat-container" >
@@ -119,36 +144,46 @@ function App() {
119144 </ button >
120145 </ div >
121146 < hr />
147+ < div className = "search-container" >
148+ < input
149+ type = "search"
150+ placeholder = { t ( 'Search conversations...' ) }
151+ value = { searchQuery }
152+ onChange = { ( e ) => setSearchQuery ( e . target . value ) }
153+ className = "search-input"
154+ aria-label = { t ( 'Search' ) }
155+ autoComplete = "off"
156+ />
157+ </ div >
122158 < div className = "chat-list" >
123- { sessions . map (
124- (
125- session ,
126- index , // TODO editable session name
127- ) => (
128- < button
129- key = { index }
130- className = { `normal-button ${ sessionId === session . sessionId ? 'active' : '' } ` }
131- style = "display: flex; align-items: center; justify-content: space-between;"
132- onClick = { ( ) => {
133- setSessionIdSafe ( session . sessionId )
134- } }
135- >
136- { session . sessionName }
137- < span className = "gpt-util-group" >
138- < DeleteButton
139- size = { 14 }
140- text = { t ( 'Delete Conversation' ) }
141- onConfirm = { ( ) =>
142- deleteSession ( session . sessionId ) . then ( ( sessions ) => {
143- setSessions ( sessions )
144- setSessionIdSafe ( sessions [ 0 ] . sessionId )
145- } )
146- }
147- />
148- </ span >
149- </ button >
150- ) ,
151- ) }
159+ { filteredSessions . map ( ( session ) => (
160+ < button
161+ key = { session . sessionId }
162+ className = { `normal-button ${ sessionId === session . sessionId ? 'active' : '' } ` }
163+ style = { {
164+ display : 'flex' ,
165+ alignItems : 'center' ,
166+ justifyContent : 'space-between' ,
167+ } }
168+ onClick = { ( ) => {
169+ setSessionIdSafe ( session . sessionId )
170+ } }
171+ >
172+ { session . sessionName }
173+ < span className = "gpt-util-group" >
174+ < DeleteButton
175+ size = { 14 }
176+ text = { t ( 'Delete Conversation' ) }
177+ onConfirm = { ( ) =>
178+ deleteSession ( session . sessionId ) . then ( ( sessions ) => {
179+ setSessions ( sessions )
180+ setSessionIdSafe ( sessions [ 0 ] . sessionId )
181+ } )
182+ }
183+ />
184+ </ span >
185+ </ button >
186+ ) ) }
152187 </ div >
153188 < hr />
154189 < div className = "chat-sidebar-button-group" >
@@ -165,7 +200,7 @@ function App() {
165200 </ div >
166201 < div className = "chat-content" >
167202 { renderContent && currentSession && currentSession . conversationRecords && (
168- < div className = "chatgptbox-container" style = " height:100%;" >
203+ < div className = "chatgptbox-container" style = { { height : ' 100%' } } >
169204 < ConversationCard
170205 session = { currentSession }
171206 notClampSize = { true }
0 commit comments