PDF ekleme ve metin düzenleme eklendi

This commit is contained in:
2025-11-18 00:07:17 +03:00
parent b6155c3fcb
commit 49024fa6c9
5 changed files with 262 additions and 63 deletions

View File

@@ -5,6 +5,7 @@ import {
Button,
LinearProgress,
Stack,
TextField,
Typography,
} from '@mui/material';
import { useNavigate } from 'react-router-dom';
@@ -22,9 +23,11 @@ const OcrStep = () => {
const clearTranslation = useAppStore((state) => state.clearTranslation);
const bookMetadata = useAppStore((state) => state.bookMetadata);
const epubImports = useAppStore((state) => state.epubImports);
const pdfImports = useAppStore((state) => state.pdfImports);
const [status, setStatus] = useState('idle');
const [currentIndex, setCurrentIndex] = useState(0);
const [previewText, setPreviewText] = useState('');
const [isEditing, setIsEditing] = useState(false);
const total = croppedImages.length;
const abortRef = useRef(false);
@@ -39,6 +42,12 @@ const OcrStep = () => {
const [workerReady, setWorkerReady] = useState(false);
const previewRef = useRef(null);
// removed auto navigation to translation
const handlePreviewChange = (event) => {
if (!isEditing) return;
const value = event.target.value;
setPreviewText(value);
setOcrText(value);
};
const orderedImages = useMemo(
() => [...croppedImages].sort((a, b) => (a.order ?? 0) - (b.order ?? 0)),
@@ -119,13 +128,15 @@ const OcrStep = () => {
}, [assetBase, isDev, orderedImages.length, setError]);
useEffect(() => {
if (!orderedImages.length) return;
if (!orderedImages.length && !(epubImports.length || pdfImports.length)) return;
setStatus('idle');
setCurrentIndex(0);
setPreviewText('');
setOcrText('');
setPreviewText(ocrText || '');
if (!ocrText) {
setOcrText('');
}
clearTranslation();
}, [clearTranslation, orderedImages, setOcrText]);
}, [clearTranslation, epubImports.length, orderedImages, pdfImports.length, ocrText, setOcrText]);
useEffect(() => {
if (previewRef.current) {
@@ -176,7 +187,7 @@ const OcrStep = () => {
}, [orderedImages, setError, setOcrText, status, total, workerReady]);
if (!orderedImages.length && !epubImports.length) {
if (!orderedImages.length && !epubImports.length && !pdfImports.length) {
return (
<Stack spacing={2}>
<Alert severity="info">Önce görselleri cropla.</Alert>
@@ -187,7 +198,8 @@ const OcrStep = () => {
);
}
if (!orderedImages.length && epubImports.length) {
if (!orderedImages.length && (epubImports.length || pdfImports.length)) {
const documentCount = epubImports.length + pdfImports.length;
return (
<Stack spacing={4}>
{bookMetadata && (
@@ -197,30 +209,50 @@ const OcrStep = () => {
</Typography>
)}
<Box textAlign="center">
<Typography variant="h5">EPUB metni ayrıştırıldı</Typography>
<Typography variant="h5">Belge metni ayrıştırıldı</Typography>
<Typography color="text.secondary">
{epubImports.length > 1
? `${epubImports.length} EPUB dosyasından metin çıkarıldı.`
: 'EPUB dosyasındaki metin çıkarıldı.'}
{documentCount > 1
? `${documentCount} belge dosyasından metin çıkarıldı.`
: 'Yüklediğin belgedeki metin çıkarıldı.'}
</Typography>
</Box>
<Box sx={{ p: 2, borderRadius: 2, bgcolor: 'background.default' }}>
<Typography variant="subtitle1">Ön izleme</Typography>
<Box
ref={previewRef}
sx={{
mt: 1,
maxHeight: '10em',
overflowY: 'auto',
whiteSpace: 'pre-wrap',
lineHeight: 1.5,
fontSize: '0.95rem',
color: 'text.secondary',
pr: 1,
}}
>
{ocrText?.trim() || 'Metin ayrıştırılıyor...'}
</Box>
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Typography variant="subtitle1">Ön izleme</Typography>
<Button
size="small"
variant={isEditing ? 'contained' : 'outlined'}
onClick={() => setIsEditing((prev) => !prev)}
>
{isEditing ? 'Görünüme geç' : 'Metni düzenle'}
</Button>
</Stack>
{isEditing ? (
<TextField
fullWidth
multiline
minRows={6}
value={previewText}
onChange={handlePreviewChange}
sx={{ mt: 1 }}
/>
) : (
<Box
ref={previewRef}
sx={{
mt: 1,
maxHeight: '10em',
overflowY: 'auto',
whiteSpace: 'pre-wrap',
lineHeight: 1.5,
fontSize: '0.95rem',
color: 'text.secondary',
pr: 1,
}}
>
{previewText || ocrText?.trim() || 'Metin ayrıştırılıyor...'}
</Box>
)}
</Box>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} justifyContent="space-between">
<Button variant="contained" onClick={() => navigate('/')}>
@@ -272,22 +304,42 @@ const OcrStep = () => {
</Typography>
</Box>
<Box sx={{ p: 2, borderRadius: 2, bgcolor: 'background.default' }}>
<Typography variant="subtitle1">Ön izleme</Typography>
<Box
ref={previewRef}
sx={{
mt: 1,
maxHeight: '8.5em',
overflowY: 'auto',
whiteSpace: 'pre-wrap',
lineHeight: 1.5,
fontSize: '0.95rem',
color: 'text.secondary',
pr: 1,
}}
>
{previewText || 'Metin bekleniyor'}
</Box>
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Typography variant="subtitle1">Ön izleme</Typography>
<Button
size="small"
variant={isEditing ? 'contained' : 'outlined'}
onClick={() => setIsEditing((prev) => !prev)}
>
{isEditing ? 'Görünüme geç' : 'Metni düzenle'}
</Button>
</Stack>
{isEditing ? (
<TextField
fullWidth
multiline
minRows={6}
value={previewText}
onChange={handlePreviewChange}
sx={{ mt: 1 }}
/>
) : (
<Box
ref={previewRef}
sx={{
mt: 1,
maxHeight: '8.5em',
overflowY: 'auto',
whiteSpace: 'pre-wrap',
lineHeight: 1.5,
fontSize: '0.95rem',
color: 'text.secondary',
pr: 1,
}}
>
{previewText || 'Metin bekleniyor'}
</Box>
)}
</Box>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} justifyContent="space-between">
<Button variant="contained" onClick={() => navigate('/bulk-crop')}>