130 lines
3.8 KiB
TypeScript
130 lines
3.8 KiB
TypeScript
import clsx from 'clsx';
|
|
import React from 'react';
|
|
|
|
import Button from '@/components/Button';
|
|
import { useEnv } from '@/context/EnvContext';
|
|
import { useTranslation } from '@/hooks/useTranslation';
|
|
import { useBookDataStore } from '@/store/bookDataStore';
|
|
import { useReaderStore } from '@/store/readerStore';
|
|
import { useReviewModeStore } from '@/store/reviewModeStore';
|
|
import { eventDispatcher } from '@/utils/event';
|
|
import {
|
|
canLaunchInlineReviewEditor,
|
|
launchInlineReviewEditor,
|
|
loadInlineReviewData,
|
|
} from '@/services/reviewEditorService';
|
|
|
|
interface ReviewModeTogglerProps {
|
|
bookKey: string;
|
|
}
|
|
|
|
const ReviewModeToggler: React.FC<ReviewModeTogglerProps> = ({ bookKey }) => {
|
|
const _ = useTranslation();
|
|
const { appService } = useEnv();
|
|
const { setHoveredBookKey } = useReaderStore();
|
|
const bookData = useBookDataStore((state) => state.getBookData(bookKey));
|
|
const reviewState = useReviewModeStore((state) => state.books[bookKey]);
|
|
const {
|
|
setActiveBookKey,
|
|
setPanelVisible,
|
|
setBookLoading,
|
|
setBookError,
|
|
setBookEnabled,
|
|
setBookData,
|
|
} = useReviewModeStore();
|
|
|
|
const enabled = !!reviewState?.enabled;
|
|
const loading = !!reviewState?.loading;
|
|
|
|
if (!canLaunchInlineReviewEditor(appService) || bookData?.book?.format !== 'EPUB') return null;
|
|
|
|
const handleToggleReviewMode = async () => {
|
|
if (appService?.isMobile) {
|
|
setHoveredBookKey('');
|
|
}
|
|
|
|
if (enabled) {
|
|
if (
|
|
reviewState?.hasUnsavedEdit &&
|
|
appService &&
|
|
!(await appService.ask('当前段落有未保存的修改,确定关闭审校模式吗?'))
|
|
) {
|
|
return;
|
|
}
|
|
setBookEnabled(bookKey, false);
|
|
return;
|
|
}
|
|
|
|
if (!bookData?.book) {
|
|
setBookError(bookKey, _('Unable to open book'));
|
|
return;
|
|
}
|
|
|
|
const activeState = useReviewModeStore.getState();
|
|
const activeReview = activeState.books[activeState.activeBookKey || ''];
|
|
if (
|
|
activeState.activeBookKey !== bookKey &&
|
|
activeReview?.hasUnsavedEdit &&
|
|
appService &&
|
|
!(await appService.ask('另一册书的当前段落有未保存修改,确定切换审校书籍吗?'))
|
|
) {
|
|
return;
|
|
}
|
|
if (activeState.activeBookKey && activeReview?.hasUnsavedEdit) {
|
|
activeState.setBookUnsavedEdit(activeState.activeBookKey, false);
|
|
}
|
|
|
|
setActiveBookKey(bookKey);
|
|
setPanelVisible(true);
|
|
setBookLoading(bookKey, true);
|
|
|
|
try {
|
|
const launch = await launchInlineReviewEditor(appService, bookData.book);
|
|
const data = await loadInlineReviewData(
|
|
launch.url,
|
|
launch.sessionId,
|
|
launch.accessToken,
|
|
);
|
|
setBookData(bookKey, {
|
|
baseUrl: launch.url,
|
|
accessToken: launch.accessToken,
|
|
sessionId: launch.sessionId,
|
|
reviewRoot: launch.reviewRoot,
|
|
version: launch.version,
|
|
session: data.session,
|
|
rows: data.rows,
|
|
gptConfig: data.gptConfig,
|
|
selectedRowId: data.rows[0]?.id || '',
|
|
});
|
|
setBookEnabled(bookKey, true);
|
|
eventDispatcher.dispatch('toast', {
|
|
type: 'info',
|
|
message: data.rows.length
|
|
? `审校模式已开启,共 ${data.rows.length} 段`
|
|
: '审校模式已开启,但当前 EPUB 没有识别到双语段落',
|
|
timeout: 2500,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : String(error);
|
|
setBookError(bookKey, message);
|
|
eventDispatcher.dispatch('toast', {
|
|
type: 'error',
|
|
message,
|
|
timeout: 3500,
|
|
});
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Button
|
|
icon={<span className='text-sm font-semibold leading-none'>校</span>}
|
|
onClick={handleToggleReviewMode}
|
|
disabled={loading}
|
|
label={enabled ? _('Disable Review Mode') : _('Review Mode')}
|
|
className={clsx(enabled && 'bg-base-300/50')}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export default ReviewModeToggler;
|