Skip to content

Commit d8deda1

Browse files
Address review feedback: fix React patterns, accessibility, and performance
Co-authored-by: PeterDaveHello <[email protected]>
1 parent 96fddb6 commit d8deda1

File tree

3 files changed

+64
-52
lines changed

3 files changed

+64
-52
lines changed

src/_locales/zh-hant/main.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"Clear conversations": "清空對話記錄",
9999
"Settings": "設定",
100100
"Search": "搜尋",
101-
"Search conversations...": "搜尋聊天記錄...",
101+
"Search conversations...": "搜尋對話記錄...",
102102
"Feature Pages": "功能頁面",
103103
"Keyboard Shortcuts": "快速鍵設定",
104104
"Open Conversation Page": "開啟獨立對話頁面",

src/pages/IndependentPanel/App.jsx

Lines changed: 52 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
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'
1010
import './styles.scss'
1111
import { useConfig } from '../../hooks/use-config.mjs'
1212
import { useTranslation } from 'react-i18next'
@@ -104,28 +104,29 @@ function App() {
104104
await setSessionIdSafe(sessions[0].sessionId)
105105
}
106106

107-
// Filter sessions based on search query
108-
const filteredSessions = sessions.filter((session) => {
109-
if (!searchQuery.trim()) return true
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
110111

111-
const query = searchQuery.toLowerCase()
112-
113-
// Search in session name
114-
if (session.sessionName && session.sessionName.toLowerCase().includes(query)) {
115-
return true
116-
}
112+
return sessions.filter((session) => {
113+
// Search in session name
114+
if (session.sessionName && session.sessionName.toLowerCase().includes(query)) {
115+
return true
116+
}
117117

118-
// Search in conversation records
119-
if (session.conversationRecords && Array.isArray(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-
}
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+
}
126126

127-
return false
128-
})
127+
return false
128+
})
129+
}, [sessions, searchQuery])
129130

130131
return (
131132
<div className="IndependentPanel">
@@ -145,43 +146,44 @@ function App() {
145146
<hr />
146147
<div className="search-container">
147148
<input
148-
type="text"
149+
type="search"
149150
placeholder={t('Search conversations...')}
150151
value={searchQuery}
151152
onChange={(e) => setSearchQuery(e.target.value)}
152153
className="search-input"
154+
aria-label={t('Search')}
155+
autoComplete="off"
153156
/>
154157
</div>
155158
<div className="chat-list">
156-
{filteredSessions.map(
157-
(
158-
session,
159-
index, // TODO editable session name
160-
) => (
161-
<button
162-
key={index}
163-
className={`normal-button ${sessionId === session.sessionId ? 'active' : ''}`}
164-
style="display: flex; align-items: center; justify-content: space-between;"
165-
onClick={() => {
166-
setSessionIdSafe(session.sessionId)
167-
}}
168-
>
169-
{session.sessionName}
170-
<span className="gpt-util-group">
171-
<DeleteButton
172-
size={14}
173-
text={t('Delete Conversation')}
174-
onConfirm={() =>
175-
deleteSession(session.sessionId).then((sessions) => {
176-
setSessions(sessions)
177-
setSessionIdSafe(sessions[0].sessionId)
178-
})
179-
}
180-
/>
181-
</span>
182-
</button>
183-
),
184-
)}
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+
))}
185187
</div>
186188
<hr />
187189
<div className="chat-sidebar-button-group">

src/pages/IndependentPanel/styles.scss

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@
7171
width: 60px;
7272
}
7373

74+
.chat-sidebar.collapsed .search-container {
75+
display: none;
76+
}
77+
7478
.chat-sidebar:hover,
7579
.chat-sidebar:not(.collapsed) {
7680
min-width: 250px;
@@ -100,6 +104,8 @@
100104
color: var(--font-color);
101105
font-size: 14px;
102106
font-family: 'Cairo', sans-serif;
107+
box-sizing: border-box;
108+
line-height: 1.2;
103109
}
104110

105111
.search-input::placeholder {
@@ -108,10 +114,14 @@
108114
}
109115

110116
.search-input:focus {
111-
outline: none;
112117
border-color: var(--font-active-color);
113118
}
114119

120+
.search-input:focus-visible {
121+
outline: 2px solid var(--font-active-color);
122+
outline-offset: 2px;
123+
}
124+
115125
.chat-list {
116126
display: flex;
117127
flex-direction: column;

0 commit comments

Comments
 (0)