镜像自地址
https://github.com/lhly/search-syntax-pro.git
已同步 2026-10-20 14:27:47 +08:00
feat(历史记录): 添加popup显示限制和设置页确认逻辑
添加popup页面最多显示50条记录的限制,并在设置页面添加历史记录超出限制时的确认逻辑 当历史记录超过限制时,显示提示信息并引导用户前往设置页面
这个提交包含在:
父节点
d64d047a36
当前提交
22f8b16839
@ -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,6 +157,8 @@ export function SearchHistory({ history, onRestore, onClear }: SearchHistoryProp
|
||||
>
|
||||
{showAll
|
||||
? t('searchHistory.collapse')
|
||||
: reachedLimit
|
||||
? t('searchHistory.expandLimit', { limit: POPUP_MAX_DISPLAY })
|
||||
: t('searchHistory.expandAll', { count: history.length })
|
||||
}
|
||||
</button>
|
||||
@ -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) {
|
||||
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>
|
||||
)}
|
||||
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户