diff --git a/lyrics_transcriber/correction/corrector.py b/lyrics_transcriber/correction/corrector.py index bc61283..2a3dab0 100644 --- a/lyrics_transcriber/correction/corrector.py +++ b/lyrics_transcriber/correction/corrector.py @@ -38,9 +38,9 @@ def __init__( NoSpacePunctuationMatchHandler(), SyllablesMatchHandler(), ExtendAnchorHandler(), - RepeatCorrectionHandler(), - SoundAlikeHandler(), - LevenshteinHandler(), + # RepeatCorrectionHandler(), + # SoundAlikeHandler(), + # LevenshteinHandler(), ] @property @@ -134,7 +134,7 @@ def _process_corrections( def _process_gaps(self, gap_sequences: List[GapSequence]) -> List[WordCorrection]: """Process each gap using available handlers until all words are corrected or no handlers remain.""" all_corrections = [] - return all_corrections + # return all_corrections for gap in gap_sequences: self.logger.debug(f"Processing gap: {gap.text}") diff --git a/lyrics_transcriber/frontend/src/components/WordEditControls.tsx b/lyrics_transcriber/frontend/src/components/WordEditControls.tsx new file mode 100644 index 0000000..e9a5b50 --- /dev/null +++ b/lyrics_transcriber/frontend/src/components/WordEditControls.tsx @@ -0,0 +1,116 @@ +import { Button, Box, TextField } from '@mui/material' +import DeleteIcon from '@mui/icons-material/Delete' +import { useState, useEffect } from 'react' +import { ModalContent } from './LyricsAnalyzer' + +interface WordEditControlsProps { + content: ModalContent + onUpdateCorrection?: (position: number, updatedWords: string[]) => void + onClose: () => void +} + +export function useWordEdit(content: ModalContent | null) { + const [editedWord, setEditedWord] = useState('') + const [isEditing, setIsEditing] = useState(false) + + useEffect(() => { + if (content) { + setEditedWord(content.type === 'gap' ? content.data.word : content.type === 'anchor' ? content.data.words[0] : '') + setIsEditing(false) + } + }, [content]) + + return { + editedWord, + setEditedWord, + isEditing, + setIsEditing + } +} + +export default function WordEditControls({ content, onUpdateCorrection, onClose }: WordEditControlsProps) { + const { + editedWord, + setEditedWord, + isEditing, + setIsEditing + } = useWordEdit(content) + + const handleStartEdit = () => { + if (content.type === 'gap') { + setEditedWord(content.data.word) + } else if (content.type === 'anchor') { + setEditedWord(content.data.words[0]) + } + setIsEditing(true) + } + + const handleDelete = () => { + if (!onUpdateCorrection) return + onUpdateCorrection(content.data.position, []) + onClose() + } + + const handleSaveEdit = () => { + if (onUpdateCorrection) { + onUpdateCorrection(content.data.position, [editedWord]) + } + onClose() + } + + const handleCancelEdit = () => { + if (content.type === 'gap') { + setEditedWord(content.data.word) + setIsEditing(false) + } + } + + const handleWordChange = (event: React.ChangeEvent) => { + setEditedWord(event.target.value) + } + + return isEditing ? ( + + + + + + + + + ) : ( + + + + + ) +} \ No newline at end of file diff --git a/lyrics_transcriber/frontend/tsconfig.tsbuildinfo b/lyrics_transcriber/frontend/tsconfig.tsbuildinfo index ddb3c78..540e692 100644 --- a/lyrics_transcriber/frontend/tsconfig.tsbuildinfo +++ b/lyrics_transcriber/frontend/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/app.tsx","./src/api.ts","./src/main.tsx","./src/types.ts","./src/vite-env.d.ts","./src/components/correctionmetrics.tsx","./src/components/detailsmodal.tsx","./src/components/fileupload.tsx","./src/components/lyricsanalyzer.tsx","./src/components/modeselector.tsx","./src/components/referenceview.tsx","./src/components/transcriptionview.tsx","./src/components/shared/constants.ts","./src/components/shared/styles.ts","./src/components/shared/types.ts","./src/components/shared/components/highlightedtext.tsx","./src/components/shared/components/sourceselector.tsx","./src/components/shared/components/word.tsx","./src/components/shared/hooks/usewordclick.ts","./src/components/shared/utils/newlinecalculator.ts","./src/components/shared/utils/positioncalculator.ts"],"version":"5.6.3"} \ No newline at end of file +{"root":["./src/app.tsx","./src/api.ts","./src/main.tsx","./src/types.ts","./src/vite-env.d.ts","./src/components/correctionmetrics.tsx","./src/components/detailsmodal.tsx","./src/components/fileupload.tsx","./src/components/lyricsanalyzer.tsx","./src/components/modeselector.tsx","./src/components/referenceview.tsx","./src/components/transcriptionview.tsx","./src/components/wordeditcontrols.tsx","./src/components/shared/constants.ts","./src/components/shared/styles.ts","./src/components/shared/types.ts","./src/components/shared/components/highlightedtext.tsx","./src/components/shared/components/sourceselector.tsx","./src/components/shared/components/word.tsx","./src/components/shared/hooks/usewordclick.ts","./src/components/shared/utils/newlinecalculator.ts","./src/components/shared/utils/positioncalculator.ts"],"version":"5.6.3"} \ No newline at end of file diff --git a/lyrics_transcriber/review/server.py b/lyrics_transcriber/review/server.py index 491c03f..1678e47 100644 --- a/lyrics_transcriber/review/server.py +++ b/lyrics_transcriber/review/server.py @@ -99,6 +99,8 @@ def start_review_server(correction_result: CorrectionResult) -> CorrectionResult import uvicorn import webbrowser from threading import Thread + import signal + import sys global current_review, review_completed current_review = correction_result @@ -110,8 +112,12 @@ def start_review_server(correction_result: CorrectionResult) -> CorrectionResult start_vite_server() logger.info("Frontend assets mounted") + # Create a custom server config + config = uvicorn.Config(app, host="127.0.0.1", port=8000, log_level="info") + server = uvicorn.Server(config) + # Start FastAPI server in a separate thread - server_thread = Thread(target=uvicorn.run, args=(app,), kwargs={"host": "127.0.0.1", "port": 8000, "log_level": "info"}, daemon=True) + server_thread = Thread(target=server.run, daemon=True) server_thread.start() logger.info("Server thread started") @@ -125,9 +131,9 @@ def start_review_server(correction_result: CorrectionResult) -> CorrectionResult start_time = time.time() while not review_completed: time.sleep(0.1) - # if time.time() - start_time > 600: # 10 minute timeout - # logger.error("Review timed out after 10 minutes") - # raise TimeoutError("Review did not complete within the expected time frame.") - logger.info("Review completed, returning results") + logger.info("Review completed, shutting down server...") + server.should_exit = True + server_thread.join(timeout=5) # Wait up to 5 seconds for server to shut down + return current_review