feat(历史记录): 添加popup显示限制和设置页确认逻辑

添加popup页面最多显示50条记录的限制,并在设置页面添加历史记录超出限制时的确认逻辑
当历史记录超过限制时,显示提示信息并引导用户前往设置页面
这个提交包含在:
Zain 2025-11-08 15:53:02 +08:00
父节点 d64d047a36
当前提交 22f8b16839
共有 3 个文件被更改,包括 88 次插入 和 7 次删除

查看文件

@ -63,9 +63,15 @@ export function SearchHistory({ history, onRestore, onClear }: SearchHistoryProp
return badges
}
// Popup页面显示上限配置
const POPUP_MAX_DISPLAY = 50 // popup页面最多显示50条记录
// 计算要显示的记录数
const displayCount = showAll ? history.length : 10
const displayCount = showAll
? Math.min(history.length, POPUP_MAX_DISPLAY) // 展开时最多显示50条
: 10 // 默认显示10条
const hasMore = history.length > 10
const reachedLimit = history.length > POPUP_MAX_DISPLAY // 是否超过popup显示上限
return (
<div className="card p-4">
@ -139,7 +145,9 @@ export function SearchHistory({ history, onRestore, onClear }: SearchHistoryProp
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3">
<p className="text-xs text-blue-700 dark:text-blue-300 text-center mb-2">
{showAll
? t('searchHistory.showingAll', { count: history.length })
? reachedLimit
? t('searchHistory.showingLimit', { limit: POPUP_MAX_DISPLAY, total: history.length })
: t('searchHistory.showingAll', { count: displayCount })
: t('searchHistory.showingRecent', { showing: 10, total: history.length })
}
</p>
@ -149,7 +157,9 @@ export function SearchHistory({ history, onRestore, onClear }: SearchHistoryProp
>
{showAll
? t('searchHistory.collapse')
: t('searchHistory.expandAll', { count: history.length })
: reachedLimit
? t('searchHistory.expandLimit', { limit: POPUP_MAX_DISPLAY })
: t('searchHistory.expandAll', { count: history.length })
}
</button>
{!showAll && (
@ -157,6 +167,22 @@ export function SearchHistory({ history, onRestore, onClear }: SearchHistoryProp
{t('searchHistory.viewAllHint')}
</p>
)}
{/* 当已展开且超过上限时,显示引导到设置页面的提示 */}
{showAll && reachedLimit && (
<div className="mt-3 pt-3 border-t border-blue-200 dark:border-blue-700">
<p className="text-xs text-blue-600 dark:text-blue-400 text-center mb-2">
💡 {t('searchHistory.viewAllInSettings', { total: history.length })}
</p>
<button
onClick={() => {
chrome.runtime.openOptionsPage()
}}
className="w-full btn btn-sm btn-ghost text-blue-600 dark:text-blue-400 hover:bg-blue-100 dark:hover:bg-blue-900/30"
>
{t('searchHistory.goToSettings')} →
</button>
</div>
)}
</div>
</div>
)}

查看文件

@ -51,9 +51,13 @@ const translations: Record<Language, Record<string, string>> = {
'searchHistory.unknownTime': '未知时间',
'searchHistory.showingAll': '已展开全部 {count} 条记录',
'searchHistory.showingRecent': '显示最近 {showing} 条,共 {total} 条',
'searchHistory.showingLimit': '已显示最近 {limit} 条,共 {total} 条记录',
'searchHistory.expandAll': '展开全部 {count} 条记录 ↓',
'searchHistory.expandLimit': '展开至 {limit} 条记录 ↓',
'searchHistory.collapse': '收起历史记录 ↑',
'searchHistory.viewAllHint': '或前往设置页面查看完整历史记录',
'searchHistory.viewAllInSettings': '查看全部 {total} 条记录,请前往设置页面',
'searchHistory.goToSettings': '打开设置页面',
'options.header.title': '搜索语法大师 - 设置',
'options.header.subtitle': '设置和配置',
'options.tabs.settings': '设置',
@ -82,6 +86,8 @@ const translations: Record<Language, Record<string, string>> = {
'options.actions.save': '保存设置',
'options.actions.saving': '保存中...',
'options.messages.saveSuccess': '设置已保存',
'options.messages.saveSuccessWithTrim': '设置已保存,已删除超出限制的 {removed} 条历史记录',
'options.messages.saveCancelled': '已取消保存',
'options.messages.saveFailure': '保存失败',
'options.messages.resetSuccess': '设置已重置为默认值并自动保存',
'options.messages.resetFailure': '重置设置失败',
@ -90,6 +96,7 @@ const translations: Record<Language, Record<string, string>> = {
'options.confirm.clearAll': '确定要清除所有数据吗?这将删除搜索历史、设置等所有信息,且无法恢复。',
'options.confirm.clearAllSecond': '请再次确认:此操作不可撤销!',
'options.confirm.clearHistory': '确定要清除所有历史记录吗?此操作无法恢复。',
'options.confirm.trimHistory': '当前有 {current} 条历史记录,新限制为 {limit} 条。\n\n这将立即删除最旧的 {willDelete} 条记录,此操作不可撤销。\n\n是否继续?',
'options.alert.importSuccess': '数据导入成功!页面将重新加载。',
'options.alert.importFailure': '导入失败: {error}',
'options.alert.importInvalid': '无效的备份文件格式',
@ -162,9 +169,13 @@ const translations: Record<Language, Record<string, string>> = {
'searchHistory.unknownTime': 'Unknown time',
'searchHistory.showingAll': 'Showing all {count} records',
'searchHistory.showingRecent': 'Showing latest {showing} of {total} records',
'searchHistory.showingLimit': 'Showing latest {limit} of {total} records',
'searchHistory.expandAll': 'Show all {count} records ↓',
'searchHistory.expandLimit': 'Show up to {limit} records ↓',
'searchHistory.collapse': 'Collapse history ↑',
'searchHistory.viewAllHint': 'Or visit settings page to view complete history',
'searchHistory.viewAllInSettings': 'To view all {total} records, please visit Settings page',
'searchHistory.goToSettings': 'Open Settings',
'options.header.title': 'SearchSyntax Pro - Settings',
'options.header.subtitle': 'Settings & configuration',
'options.tabs.settings': 'Settings',
@ -193,6 +204,8 @@ const translations: Record<Language, Record<string, string>> = {
'options.actions.save': 'Save settings',
'options.actions.saving': 'Saving...',
'options.messages.saveSuccess': 'Settings saved',
'options.messages.saveSuccessWithTrim': 'Settings saved, removed {removed} history entries exceeding limit',
'options.messages.saveCancelled': 'Save cancelled',
'options.messages.saveFailure': 'Failed to save settings',
'options.messages.resetSuccess': 'Settings have been reset to defaults and automatically saved',
'options.messages.resetFailure': 'Failed to reset settings',
@ -201,6 +214,7 @@ const translations: Record<Language, Record<string, string>> = {
'options.confirm.clearAll': 'Are you sure you want to clear all data? This will delete history, settings, and cannot be undone.',
'options.confirm.clearAllSecond': 'Please confirm again: this action cannot be undone!',
'options.confirm.clearHistory': 'Are you sure you want to clear all history? This action cannot be undone.',
'options.confirm.trimHistory': 'You currently have {current} history entries, but the new limit is {limit}.\n\nThis will immediately delete the oldest {willDelete} entries. This action cannot be undone.\n\nContinue?',
'options.alert.importSuccess': 'Data imported successfully! The page will reload.',
'options.alert.importFailure': 'Import failed: {error}',
'options.alert.importInvalid': 'Invalid backup file format',

查看文件

@ -12,7 +12,7 @@ function App() {
const [settings, setSettings] = useState<UserSettings | null>(null)
const [loading, setLoading] = useState(true)
const [saving, setSaving] = useState(false)
const [message, setMessage] = useState<{ type: 'success' | 'error'; key: string } | null>(null)
const [message, setMessage] = useState<{ type: 'success' | 'error'; key: string; params?: Record<string, string> } | null>(null)
const [history, setHistory] = useState<SearchHistory[]>([])
const [activeTab, setActiveTab] = useState<'settings' | 'history'>('settings')
@ -49,13 +49,54 @@ function App() {
setMessage(null)
try {
// 检查是否需要清理历史记录
const currentHistoryData = await chrome.storage.local.get('search_history')
const currentHistory: SearchHistory[] = currentHistoryData.search_history || []
const willDelete = currentHistory.length - settings.historyLimit
// 如果当前记录超过新限制,需要用户确认
if (willDelete > 0) {
const confirmed = confirm(
translate(language, 'options.confirm.trimHistory', {
current: currentHistory.length.toString(),
limit: settings.historyLimit.toString(),
willDelete: willDelete.toString()
})
)
if (!confirmed) {
// 用户取消,不保存设置
setSaving(false)
setMessage({ type: 'error', key: 'options.messages.saveCancelled' })
setTimeout(() => setMessage(null), 3000)
return
}
// 用户确认,立即清理超出的记录(保留最新的N条)
const trimmedHistory = currentHistory.slice(0, settings.historyLimit)
await chrome.storage.local.set({ search_history: trimmedHistory })
// 更新本地状态
setHistory(trimmedHistory)
}
// 保存设置
const success = await saveSettings(settings)
if (success) {
setMessage({ type: 'success', key: 'options.messages.saveSuccess' })
if (willDelete > 0) {
setMessage({
type: 'success',
key: 'options.messages.saveSuccessWithTrim',
params: { removed: willDelete.toString() }
})
} else {
setMessage({ type: 'success', key: 'options.messages.saveSuccess' })
}
} else {
setMessage({ type: 'error', key: 'options.messages.saveFailure' })
}
} catch (error) {
console.error('保存设置失败:', error)
setMessage({ type: 'error', key: 'options.messages.saveFailure' })
} finally {
setSaving(false)
@ -199,7 +240,7 @@ interface OptionsContentProps {
loading: boolean
settings: UserSettings | null
updateSettings: (updater: (prev: UserSettings) => UserSettings) => void
message: { type: 'success' | 'error'; key: string } | null
message: { type: 'success' | 'error'; key: string; params?: Record<string, string> } | null
saving: boolean
history: SearchHistory[]
activeTab: 'settings' | 'history'
@ -294,7 +335,7 @@ function OptionsContent({
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
}`}>
{t(message.key)}
{t(message.key, message.params)}
</div>
)}