@@ -191,7 +191,7 @@ function App() {
191
191
const toSafeString = ( value ) =>
192
192
typeof value === 'string' ? value : value == null ? '' : String ( value )
193
193
194
- // Filter sessions based on search query (memoized for performance)
194
+ // Normalization utility for search
195
195
const normalizeForSearch = ( value ) =>
196
196
toSafeString ( value )
197
197
. toLowerCase ( )
@@ -200,34 +200,32 @@ function App() {
200
200
. replace ( / \s + / g, ' ' )
201
201
. trim ( )
202
202
203
- const filteredSessions = useMemo ( ( ) => {
204
- const query = normalizeForSearch ( debouncedQuery ) . trim ( )
205
- // Always exclude items without a valid sessionId first
206
- const validSessions = Array . isArray ( sessions )
207
- ? sessions . filter ( ( s ) => Boolean ( s ?. sessionId ) )
208
- : [ ]
209
-
210
- if ( ! query ) return validSessions
211
-
212
- return validSessions . filter ( ( session ) => {
213
- // Search in session name
214
- const sessionName = normalizeForSearch ( session . sessionName )
215
- if ( sessionName . includes ( query ) ) {
216
- return true
217
- }
203
+ // Precompute a normalized index for sessions to reduce per-keystroke work
204
+ const normalizedIndex = useMemo ( ( ) => {
205
+ if ( ! Array . isArray ( sessions ) ) return [ ]
206
+ const SEP = '\n—\n'
207
+ return sessions
208
+ . filter ( ( s ) => Boolean ( s ?. sessionId ) )
209
+ . map ( ( s ) => {
210
+ const nameNorm = normalizeForSearch ( s . sessionName )
211
+ let bodyNorm = ''
212
+ if ( Array . isArray ( s . conversationRecords ) ) {
213
+ bodyNorm = s . conversationRecords
214
+ . map ( ( r ) => `${ normalizeForSearch ( r ?. question ) } ${ normalizeForSearch ( r ?. answer ) } ` )
215
+ . join ( SEP )
216
+ }
217
+ return { session : s , nameNorm, bodyNorm }
218
+ } )
219
+ } , [ sessions ] )
218
220
219
- // Search in conversation records
220
- if ( Array . isArray ( session . conversationRecords ) ) {
221
- return session . conversationRecords . some ( ( record ) => {
222
- const question = normalizeForSearch ( record ?. question )
223
- const answer = normalizeForSearch ( record ?. answer )
224
- return question . includes ( query ) || answer . includes ( query )
225
- } )
226
- }
227
-
228
- return false
229
- } )
230
- } , [ sessions , debouncedQuery ] )
221
+ // Filter sessions based on search query using the precomputed index
222
+ const filteredSessions = useMemo ( ( ) => {
223
+ const q = normalizeForSearch ( debouncedQuery ) . trim ( )
224
+ if ( ! q ) return normalizedIndex . map ( ( i ) => i . session )
225
+ return normalizedIndex
226
+ . filter ( ( i ) => i . nameNorm . includes ( q ) || i . bodyNorm . includes ( q ) )
227
+ . map ( ( i ) => i . session )
228
+ } , [ normalizedIndex , debouncedQuery ] )
231
229
232
230
return (
233
231
< div className = "IndependentPanel" >
0 commit comments