镜像自地址
https://github.com/lhly/search-syntax-pro.git
已同步 2026-10-20 22:37:48 +08:00
feat(历史记录): 添加popup显示限制和设置页确认逻辑
添加popup页面最多显示50条记录的限制,并在设置页面添加历史记录超出限制时的确认逻辑 当历史记录超过限制时,显示提示信息并引导用户前往设置页面
这个提交包含在:
父节点
d64d047a36
当前提交
22f8b16839
@ -63,9 +63,15 @@ export function SearchHistory({ history, onRestore, onClear }: SearchHistoryProp
|
|||||||
return badges
|
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 hasMore = history.length > 10
|
||||||
|
const reachedLimit = history.length > POPUP_MAX_DISPLAY // 是否超过popup显示上限
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card p-4">
|
<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">
|
<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">
|
<p className="text-xs text-blue-700 dark:text-blue-300 text-center mb-2">
|
||||||
{showAll
|
{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 })
|
: t('searchHistory.showingRecent', { showing: 10, total: history.length })
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
@ -149,6 +157,8 @@ export function SearchHistory({ history, onRestore, onClear }: SearchHistoryProp
|
|||||||
>
|
>
|
||||||
{showAll
|
{showAll
|
||||||
? t('searchHistory.collapse')
|
? t('searchHistory.collapse')
|
||||||
|
: reachedLimit
|
||||||
|
? t('searchHistory.expandLimit', { limit: POPUP_MAX_DISPLAY })
|
||||||
: t('searchHistory.expandAll', { count: history.length })
|
: t('searchHistory.expandAll', { count: history.length })
|
||||||
}
|
}
|
||||||
</button>
|
</button>
|
||||||
@ -157,6 +167,22 @@ export function SearchHistory({ history, onRestore, onClear }: SearchHistoryProp
|
|||||||
{t('searchHistory.viewAllHint')}
|
{t('searchHistory.viewAllHint')}
|
||||||
</p>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -51,9 +51,13 @@ const translations: Record<Language, Record<string, string>> = {
|
|||||||
'searchHistory.unknownTime': '未知时间',
|
'searchHistory.unknownTime': '未知时间',
|
||||||
'searchHistory.showingAll': '已展开全部 {count} 条记录',
|
'searchHistory.showingAll': '已展开全部 {count} 条记录',
|
||||||
'searchHistory.showingRecent': '显示最近 {showing} 条,共 {total} 条',
|
'searchHistory.showingRecent': '显示最近 {showing} 条,共 {total} 条',
|
||||||
|
'searchHistory.showingLimit': '已显示最近 {limit} 条,共 {total} 条记录',
|
||||||
'searchHistory.expandAll': '展开全部 {count} 条记录 ↓',
|
'searchHistory.expandAll': '展开全部 {count} 条记录 ↓',
|
||||||
|
'searchHistory.expandLimit': '展开至 {limit} 条记录 ↓',
|
||||||
'searchHistory.collapse': '收起历史记录 ↑',
|
'searchHistory.collapse': '收起历史记录 ↑',
|
||||||
'searchHistory.viewAllHint': '或前往设置页面查看完整历史记录',
|
'searchHistory.viewAllHint': '或前往设置页面查看完整历史记录',
|
||||||
|
'searchHistory.viewAllInSettings': '查看全部 {total} 条记录,请前往设置页面',
|
||||||
|
'searchHistory.goToSettings': '打开设置页面',
|
||||||
'options.header.title': '搜索语法大师 - 设置',
|
'options.header.title': '搜索语法大师 - 设置',
|
||||||
'options.header.subtitle': '设置和配置',
|
'options.header.subtitle': '设置和配置',
|
||||||
'options.tabs.settings': '设置',
|
'options.tabs.settings': '设置',
|
||||||
@ -82,6 +86,8 @@ const translations: Record<Language, Record<string, string>> = {
|
|||||||
'options.actions.save': '保存设置',
|
'options.actions.save': '保存设置',
|
||||||
'options.actions.saving': '保存中...',
|
'options.actions.saving': '保存中...',
|
||||||
'options.messages.saveSuccess': '设置已保存',
|
'options.messages.saveSuccess': '设置已保存',
|
||||||
|
'options.messages.saveSuccessWithTrim': '设置已保存,已删除超出限制的 {removed} 条历史记录',
|
||||||
|
'options.messages.saveCancelled': '已取消保存',
|
||||||
'options.messages.saveFailure': '保存失败',
|
'options.messages.saveFailure': '保存失败',
|
||||||
'options.messages.resetSuccess': '设置已重置为默认值并自动保存',
|
'options.messages.resetSuccess': '设置已重置为默认值并自动保存',
|
||||||
'options.messages.resetFailure': '重置设置失败',
|
'options.messages.resetFailure': '重置设置失败',
|
||||||
@ -90,6 +96,7 @@ const translations: Record<Language, Record<string, string>> = {
|
|||||||
'options.confirm.clearAll': '确定要清除所有数据吗?这将删除搜索历史、设置等所有信息,且无法恢复。',
|
'options.confirm.clearAll': '确定要清除所有数据吗?这将删除搜索历史、设置等所有信息,且无法恢复。',
|
||||||
'options.confirm.clearAllSecond': '请再次确认:此操作不可撤销!',
|
'options.confirm.clearAllSecond': '请再次确认:此操作不可撤销!',
|
||||||
'options.confirm.clearHistory': '确定要清除所有历史记录吗?此操作无法恢复。',
|
'options.confirm.clearHistory': '确定要清除所有历史记录吗?此操作无法恢复。',
|
||||||
|
'options.confirm.trimHistory': '当前有 {current} 条历史记录,新限制为 {limit} 条。\n\n这将立即删除最旧的 {willDelete} 条记录,此操作不可撤销。\n\n是否继续?',
|
||||||
'options.alert.importSuccess': '数据导入成功!页面将重新加载。',
|
'options.alert.importSuccess': '数据导入成功!页面将重新加载。',
|
||||||
'options.alert.importFailure': '导入失败: {error}',
|
'options.alert.importFailure': '导入失败: {error}',
|
||||||
'options.alert.importInvalid': '无效的备份文件格式',
|
'options.alert.importInvalid': '无效的备份文件格式',
|
||||||
@ -162,9 +169,13 @@ const translations: Record<Language, Record<string, string>> = {
|
|||||||
'searchHistory.unknownTime': 'Unknown time',
|
'searchHistory.unknownTime': 'Unknown time',
|
||||||
'searchHistory.showingAll': 'Showing all {count} records',
|
'searchHistory.showingAll': 'Showing all {count} records',
|
||||||
'searchHistory.showingRecent': 'Showing latest {showing} of {total} records',
|
'searchHistory.showingRecent': 'Showing latest {showing} of {total} records',
|
||||||
|
'searchHistory.showingLimit': 'Showing latest {limit} of {total} records',
|
||||||
'searchHistory.expandAll': 'Show all {count} records ↓',
|
'searchHistory.expandAll': 'Show all {count} records ↓',
|
||||||
|
'searchHistory.expandLimit': 'Show up to {limit} records ↓',
|
||||||
'searchHistory.collapse': 'Collapse history ↑',
|
'searchHistory.collapse': 'Collapse history ↑',
|
||||||
'searchHistory.viewAllHint': 'Or visit settings page to view complete 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.title': 'SearchSyntax Pro - Settings',
|
||||||
'options.header.subtitle': 'Settings & configuration',
|
'options.header.subtitle': 'Settings & configuration',
|
||||||
'options.tabs.settings': 'Settings',
|
'options.tabs.settings': 'Settings',
|
||||||
@ -193,6 +204,8 @@ const translations: Record<Language, Record<string, string>> = {
|
|||||||
'options.actions.save': 'Save settings',
|
'options.actions.save': 'Save settings',
|
||||||
'options.actions.saving': 'Saving...',
|
'options.actions.saving': 'Saving...',
|
||||||
'options.messages.saveSuccess': 'Settings saved',
|
'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.saveFailure': 'Failed to save settings',
|
||||||
'options.messages.resetSuccess': 'Settings have been reset to defaults and automatically saved',
|
'options.messages.resetSuccess': 'Settings have been reset to defaults and automatically saved',
|
||||||
'options.messages.resetFailure': 'Failed to reset settings',
|
'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.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.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.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.importSuccess': 'Data imported successfully! The page will reload.',
|
||||||
'options.alert.importFailure': 'Import failed: {error}',
|
'options.alert.importFailure': 'Import failed: {error}',
|
||||||
'options.alert.importInvalid': 'Invalid backup file format',
|
'options.alert.importInvalid': 'Invalid backup file format',
|
||||||
|
|||||||
@ -12,7 +12,7 @@ function App() {
|
|||||||
const [settings, setSettings] = useState<UserSettings | null>(null)
|
const [settings, setSettings] = useState<UserSettings | null>(null)
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [saving, setSaving] = useState(false)
|
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 [history, setHistory] = useState<SearchHistory[]>([])
|
||||||
const [activeTab, setActiveTab] = useState<'settings' | 'history'>('settings')
|
const [activeTab, setActiveTab] = useState<'settings' | 'history'>('settings')
|
||||||
|
|
||||||
@ -49,13 +49,54 @@ function App() {
|
|||||||
setMessage(null)
|
setMessage(null)
|
||||||
|
|
||||||
try {
|
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)
|
const success = await saveSettings(settings)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
if (willDelete > 0) {
|
||||||
|
setMessage({
|
||||||
|
type: 'success',
|
||||||
|
key: 'options.messages.saveSuccessWithTrim',
|
||||||
|
params: { removed: willDelete.toString() }
|
||||||
|
})
|
||||||
|
} else {
|
||||||
setMessage({ type: 'success', key: 'options.messages.saveSuccess' })
|
setMessage({ type: 'success', key: 'options.messages.saveSuccess' })
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setMessage({ type: 'error', key: 'options.messages.saveFailure' })
|
setMessage({ type: 'error', key: 'options.messages.saveFailure' })
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('保存设置失败:', error)
|
||||||
setMessage({ type: 'error', key: 'options.messages.saveFailure' })
|
setMessage({ type: 'error', key: 'options.messages.saveFailure' })
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false)
|
setSaving(false)
|
||||||
@ -199,7 +240,7 @@ interface OptionsContentProps {
|
|||||||
loading: boolean
|
loading: boolean
|
||||||
settings: UserSettings | null
|
settings: UserSettings | null
|
||||||
updateSettings: (updater: (prev: UserSettings) => UserSettings) => void
|
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
|
saving: boolean
|
||||||
history: SearchHistory[]
|
history: SearchHistory[]
|
||||||
activeTab: 'settings' | 'history'
|
activeTab: 'settings' | 'history'
|
||||||
@ -294,7 +335,7 @@ function OptionsContent({
|
|||||||
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
|
? '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'
|
: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
|
||||||
}`}>
|
}`}>
|
||||||
{t(message.key)}
|
{t(message.key, message.params)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户