feat(reader): manage rules shortcut in proofread popup (#4062)

This commit is contained in:
Huang Xin
2026-05-05 16:01:26 +08:00
committed by GitHub
parent 43f72720f2
commit d66fedcab7
5 changed files with 48 additions and 10 deletions
@@ -751,7 +751,7 @@
"Search in OPDS Catalog...": "在 OPDS 目录中搜索...",
"Please log in to use advanced TTS features": "请登录以使用高级 TTS 功能",
"Word limit of 30 words exceeded.": "已超过 30 个词的限制。",
"Proofread": "校对",
"Proofread": "文字校对",
"Current selection": "当前选中内容",
"All occurrences in this book": "本书中的所有出现位置",
"All occurrences in your library": "整个书库中的所有出现位置",
@@ -764,7 +764,7 @@
"Library": "书库",
"Yes": "是",
"No": "否",
"Proofread Replacement Rules": "校对替换规则",
"Proofread Replacement Rules": "文字校对替换规则",
"Selected Text Rules": "选中文本规则",
"No selected text replacement rules": "暂无选中文本的替换规则",
"Book Specific Rules": "书籍范围规则",
@@ -783,7 +783,7 @@
"Look up text in dictionary after selection": "在字典中查找选中文本",
"Translate text after selection": "翻译选中文本",
"Read text aloud after selection": "朗读选中文本",
"Proofread text after selection": "校对选中文本",
"Proofread text after selection": "文字校对选中文本",
"{{activeCount}} active, {{pendingCount}} pending": "{{activeCount}} 进行中,{{pendingCount}} 等待中",
"{{failedCount}} failed": "{{failedCount}} 失败",
"Waiting...": "等待中...",
@@ -1103,7 +1103,7 @@
"Translate Selection": "翻译选中内容",
"Dictionary Lookup": "词典查询",
"Read Aloud Selection": "朗读选中内容",
"Proofread Selection": "校对选中内容",
"Proofread Selection": "文字校对选中内容",
"Open Settings": "打开设置",
"Open Command Palette": "打开命令面板",
"Show Keyboard Shortcuts": "显示键盘快捷键",
@@ -750,7 +750,7 @@
"Search in OPDS Catalog...": "在 OPDS 目錄中搜尋...",
"Please log in to use advanced TTS features": "請登入以使用進階 TTS 功能",
"Word limit of 30 words exceeded.": "已超過 30 個詞的限制。",
"Proofread": "校對",
"Proofread": "文字校對",
"Current selection": "目前選取內容",
"All occurrences in this book": "本書中的所有出現位置",
"All occurrences in your library": "整個書庫中的所有出現位置",
@@ -763,7 +763,7 @@
"Library": "書庫",
"Yes": "是",
"No": "否",
"Proofread Replacement Rules": "校對取代規則",
"Proofread Replacement Rules": "文字校對取代規則",
"Selected Text Rules": "已選取文字規則",
"No selected text replacement rules": "沒有已選取文字的取代規則",
"Book Specific Rules": "書籍層級規則",
@@ -782,7 +782,7 @@
"Look up text in dictionary after selection": "在字典中查找選取後的文字",
"Translate text after selection": "翻譯選取後的文字",
"Read text aloud after selection": "朗讀選取後的文字",
"Proofread text after selection": "校對選取後的文字",
"Proofread text after selection": "文字校對選取後的文字",
"{{activeCount}} active, {{pendingCount}} pending": "{{activeCount}} 進行中,{{pendingCount}} 等待中",
"{{failedCount}} failed": "{{failedCount}} 失敗",
"Waiting...": "等待中...",
@@ -1103,7 +1103,7 @@
"Translate Selection": "翻譯選取內容",
"Dictionary Lookup": "字典查詢",
"Read Aloud Selection": "朗讀選取內容",
"Proofread Selection": "校對選取內容",
"Proofread Selection": "文字校對選取內容",
"Open Settings": "開啟設定",
"Open Command Palette": "開啟指令面板",
"Show Keyboard Shortcuts": "顯示鍵盤快捷鍵",
@@ -233,4 +233,23 @@ describe('ProofreadPopup Component', () => {
expect(mockOnClose).not.toHaveBeenCalled();
});
});
describe('Manage Replacement Rules Shortcut', () => {
it('should not render manage button when onManage is not provided', () => {
renderWithProviders(<ProofreadPopup {...defaultProps} />);
expect(screen.queryByLabelText('Proofread Replacement Rules')).toBeNull();
});
it('should render manage button and invoke onManage when provided', () => {
const mockOnManage = vi.fn();
renderWithProviders(<ProofreadPopup {...defaultProps} onManage={mockOnManage} />);
const button = screen.getByLabelText('Proofread Replacement Rules');
expect(button).toBeTruthy();
fireEvent.click(button);
expect(mockOnManage).toHaveBeenCalledTimes(1);
});
});
});
@@ -46,6 +46,7 @@ import DictionaryPopup from './DictionaryPopup';
import TranslatorPopup from './TranslatorPopup';
import useShortcuts from '@/hooks/useShortcuts';
import ProofreadPopup from './ProofreadPopup';
import { setProofreadRulesVisibility } from '@/app/reader/components/ProofreadRules';
import ExportMarkdownDialog from './ExportMarkdownDialog';
const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
@@ -1019,6 +1020,10 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
popupWidth={proofreadPopupWidth}
popupHeight={proofreadPopupHeight}
onDismiss={handleDismissPopupAndSelection}
onManage={() => {
handleDismissPopupAndSelection();
setProofreadRulesVisibility(true);
}}
/>
)}
{editingAnnotation && editingAnnotation.color && selection && (
@@ -1,5 +1,6 @@
import clsx from 'clsx';
import React, { useRef, useState } from 'react';
import { RiListSettingsLine } from 'react-icons/ri';
import { useEnv } from '@/context/EnvContext';
import { useReaderStore } from '@/store/readerStore';
import { useTranslation } from '@/hooks/useTranslation';
@@ -21,6 +22,7 @@ interface ProofreadPopupProps {
popupHeight: number;
onConfirm?: (options: CreateProofreadRuleOptions) => void;
onDismiss: () => void;
onManage?: () => void;
}
const ProofreadPopup: React.FC<ProofreadPopupProps> = ({
@@ -32,6 +34,7 @@ const ProofreadPopup: React.FC<ProofreadPopupProps> = ({
popupHeight,
onConfirm,
onDismiss,
onManage,
}) => {
const _ = useTranslation();
const { envConfig } = useEnv();
@@ -124,11 +127,22 @@ const ProofreadPopup: React.FC<ProofreadPopupProps> = ({
onDismiss={onDismiss}
>
<div className='flex flex-col gap-6 p-4'>
<div className='not-eink:text-gray-400 flex gap-1 text-xs'>
<div className='not-eink:text-gray-400 flex items-center gap-1 text-xs'>
<span className='text-nowrap'>{_('Selected text:')}</span>
<span className='not-eink:text-yellow-300 line-clamp-1 select-text break-words font-medium'>
<span className='not-eink:text-yellow-300 line-clamp-1 flex-1 select-text break-words font-medium'>
&quot;{selection?.text || ''}&quot;
</span>
{onManage && (
<button
type='button'
onClick={onManage}
aria-label={_('Proofread Replacement Rules')}
title={_('Proofread Replacement Rules')}
className='not-eink:text-gray-400 not-eink:hover:bg-gray-600 not-eink:hover:text-white shrink-0 rounded p-1'
>
<RiListSettingsLine size={16} />
</button>
)}
</div>
<div className='flex items-center justify-between gap-2'>