karaoke-gen 0.103.1__py3-none-any.whl → 0.107.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- backend/Dockerfile.base +1 -0
- backend/api/routes/admin.py +226 -3
- backend/api/routes/push.py +238 -0
- backend/api/routes/users.py +14 -3
- backend/config.py +12 -1
- backend/main.py +2 -1
- backend/models/job.py +4 -0
- backend/models/user.py +20 -2
- backend/services/encoding_interface.py +4 -0
- backend/services/gce_encoding/main.py +22 -8
- backend/services/job_manager.py +68 -11
- backend/services/job_notification_service.py +4 -21
- backend/services/push_notification_service.py +409 -0
- backend/services/stripe_service.py +2 -2
- backend/tests/conftest.py +2 -1
- backend/tests/test_admin_delete_outputs.py +352 -0
- backend/tests/test_gce_encoding_worker.py +229 -0
- backend/tests/test_impersonation.py +18 -3
- backend/tests/test_job_notification_service.py +24 -58
- backend/tests/test_push_notification_service.py +460 -0
- backend/tests/test_push_routes.py +357 -0
- backend/tests/test_stripe_service.py +205 -0
- backend/tests/test_video_worker_orchestrator.py +189 -0
- backend/workers/video_worker_orchestrator.py +23 -0
- karaoke_gen/instrumental_review/server.py +145 -35
- karaoke_gen/nextjs_frontend/__init__.py +98 -0
- karaoke_gen/nextjs_frontend/out/404/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/404.html +1 -0
- karaoke_gen/nextjs_frontend/out/__next.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/01a7f8fe40f1ff47.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/112f346e31f991df.js +4 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/16d1a4dd9d8a873a.js +3 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/1ab85c362b8b0e86.js +9 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/247eb132b7f7b574.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/2b80d15cc95e4818.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/32c7eba5cd46c1bc.js +7 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/483f26794eae53d0.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/550c3b02e85f196a.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/55c5ade44387bef8.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/5628d92b5893add2.css +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/56ebf7665e4341c8.js +7 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/5997132b61dec430.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/5ea55255bce3eb9e.js +5 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/5eda89a57490b3cd.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/692f5d9e0d700c76.js +3 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/71d7a05b14f9f0f4.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/81ac355749ef3302.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/95f7e5934dbb0e5d.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/9bce8f19eaa46940.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/a9ed54eed3e14c92.js +2 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/b35cd41238ecfb17.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5bc3c3d5ebd49eb.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5c078c08db5ae32.js +5 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/be9c44a178104187.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/c4c840e18cb4861c.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/c645af7d6b65f73e.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/d2c5e2575df784d4.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/d30af02b96d81462.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/d9bdf64f4ec1e9b7.js +7 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/dcde6ed684dacd0e.js +5 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/e422cbe931246000.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/e483af34fc792d38.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/e57422aad6b897da.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/ef02697fb404726a.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/ff1a16fafef87110.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/turbopack-2d9ca3017a9deedf.js +3 -0
- karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_buildManifest.js +11 -0
- karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_clientMiddlewareManifest.json +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_ssgManifest.js +1 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._full.txt +18 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.__PAGE__.txt +5 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.txt +4 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/_not-found/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/_not-found/index.txt +18 -0
- karaoke_gen/nextjs_frontend/out/admin/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/__next.admin.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/users/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/users/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/app/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/app/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/app/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/app/__next.app.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/__next.app.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/app/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next._full.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/index.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._full.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._full.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.txt +19 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.txt +4 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.txt +4 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/manifest.webmanifest +31 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.txt +4 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next.order.txt +4 -0
- karaoke_gen/nextjs_frontend/out/order/success/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/order/success/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.txt +4 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.txt +4 -0
- karaoke_gen/nextjs_frontend/out/payment/success/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/payment/success/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/screenshots/email-action_reminder.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/email-beta_welcome.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/email-job_completion.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/example-output.avif +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/homepage-full.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/homepage-hero.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.avif +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/job-dashboard.avif +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.avif +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.png +0 -0
- karaoke_gen/nextjs_frontend/out/sw.js +183 -0
- karaoke_gen/utils/cli_args.py +3 -3
- karaoke_gen/utils/gen_cli.py +4 -0
- karaoke_gen/utils/remote_cli.py +8 -40
- {karaoke_gen-0.103.1.dist-info → karaoke_gen-0.107.0.dist-info}/METADATA +2 -1
- {karaoke_gen-0.103.1.dist-info → karaoke_gen-0.107.0.dist-info}/RECORD +244 -131
- {karaoke_gen-0.103.1.dist-info → karaoke_gen-0.107.0.dist-info}/WHEEL +1 -1
- lyrics_transcriber/correction/agentic/agent.py +83 -60
- lyrics_transcriber/correction/anchor_sequence.py +48 -3
- lyrics_transcriber/correction/corrector.py +92 -58
- lyrics_transcriber/review/server.py +165 -33
- lyrics_transcriber/utils/tracing.py +214 -0
- karaoke_gen/instrumental_review/static/index.html +0 -1695
- lyrics_transcriber/frontend/.gitignore +0 -24
- lyrics_transcriber/frontend/.yarn/releases/yarn-4.7.0.cjs +0 -935
- lyrics_transcriber/frontend/.yarnrc.yml +0 -3
- lyrics_transcriber/frontend/README.md +0 -50
- lyrics_transcriber/frontend/REPLACE_ALL_FUNCTIONALITY.md +0 -210
- lyrics_transcriber/frontend/__init__.py +0 -25
- lyrics_transcriber/frontend/e2e/agentic-corrections.spec.ts +0 -207
- lyrics_transcriber/frontend/e2e/fixtures/agentic-correction-data.json +0 -226
- lyrics_transcriber/frontend/eslint.config.js +0 -28
- lyrics_transcriber/frontend/index.html +0 -22
- lyrics_transcriber/frontend/package-lock.json +0 -4553
- lyrics_transcriber/frontend/package.json +0 -48
- lyrics_transcriber/frontend/playwright.config.ts +0 -69
- lyrics_transcriber/frontend/public/android-chrome-192x192.png +0 -0
- lyrics_transcriber/frontend/public/android-chrome-512x512.png +0 -0
- lyrics_transcriber/frontend/src/App.tsx +0 -243
- lyrics_transcriber/frontend/src/api.ts +0 -262
- lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx +0 -111
- lyrics_transcriber/frontend/src/components/AddLyricsModal.tsx +0 -114
- lyrics_transcriber/frontend/src/components/AgenticCorrectionMetrics.tsx +0 -204
- lyrics_transcriber/frontend/src/components/AppHeader.tsx +0 -65
- lyrics_transcriber/frontend/src/components/AudioPlayer.tsx +0 -180
- lyrics_transcriber/frontend/src/components/CorrectedWordWithActions.tsx +0 -175
- lyrics_transcriber/frontend/src/components/CorrectionAnnotationModal.tsx +0 -359
- lyrics_transcriber/frontend/src/components/CorrectionDetailCard.tsx +0 -281
- lyrics_transcriber/frontend/src/components/CorrectionMetrics.tsx +0 -162
- lyrics_transcriber/frontend/src/components/DurationTimelineView.tsx +0 -257
- lyrics_transcriber/frontend/src/components/EditActionBar.tsx +0 -94
- lyrics_transcriber/frontend/src/components/EditModal.tsx +0 -720
- lyrics_transcriber/frontend/src/components/EditTimelineSection.tsx +0 -592
- lyrics_transcriber/frontend/src/components/EditWordList.tsx +0 -431
- lyrics_transcriber/frontend/src/components/FileUpload.tsx +0 -77
- lyrics_transcriber/frontend/src/components/FindReplaceModal.tsx +0 -467
- lyrics_transcriber/frontend/src/components/Header.tsx +0 -520
- lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +0 -1526
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/SyncControls.tsx +0 -216
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/TimelineCanvas.tsx +0 -721
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/UpcomingWordsBar.tsx +0 -80
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/index.tsx +0 -999
- lyrics_transcriber/frontend/src/components/MetricsDashboard.tsx +0 -51
- lyrics_transcriber/frontend/src/components/ModeSelectionModal.tsx +0 -127
- lyrics_transcriber/frontend/src/components/ModeSelector.tsx +0 -67
- lyrics_transcriber/frontend/src/components/ModelSelector.tsx +0 -23
- lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +0 -177
- lyrics_transcriber/frontend/src/components/ReferenceView.tsx +0 -268
- lyrics_transcriber/frontend/src/components/ReplaceAllLyricsModal.tsx +0 -336
- lyrics_transcriber/frontend/src/components/ReviewChangesModal.tsx +0 -354
- lyrics_transcriber/frontend/src/components/SegmentDetailsModal.tsx +0 -64
- lyrics_transcriber/frontend/src/components/TimelineEditor.tsx +0 -383
- lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +0 -131
- lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +0 -266
- lyrics_transcriber/frontend/src/components/WordDivider.tsx +0 -191
- lyrics_transcriber/frontend/src/components/shared/components/HighlightedText.tsx +0 -466
- lyrics_transcriber/frontend/src/components/shared/components/SourceSelector.tsx +0 -56
- lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +0 -89
- lyrics_transcriber/frontend/src/components/shared/constants.ts +0 -30
- lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +0 -180
- lyrics_transcriber/frontend/src/components/shared/styles.ts +0 -13
- lyrics_transcriber/frontend/src/components/shared/types.js +0 -2
- lyrics_transcriber/frontend/src/components/shared/types.ts +0 -135
- lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +0 -177
- lyrics_transcriber/frontend/src/components/shared/utils/localStorage.ts +0 -78
- lyrics_transcriber/frontend/src/components/shared/utils/referenceLineCalculator.ts +0 -75
- lyrics_transcriber/frontend/src/components/shared/utils/segmentOperations.ts +0 -360
- lyrics_transcriber/frontend/src/components/shared/utils/timingUtils.ts +0 -110
- lyrics_transcriber/frontend/src/components/shared/utils/wordUtils.ts +0 -22
- lyrics_transcriber/frontend/src/hooks/useManualSync.ts +0 -537
- lyrics_transcriber/frontend/src/main.tsx +0 -11
- lyrics_transcriber/frontend/src/theme.ts +0 -406
- lyrics_transcriber/frontend/src/types/global.d.ts +0 -9
- lyrics_transcriber/frontend/src/types.js +0 -2
- lyrics_transcriber/frontend/src/types.ts +0 -199
- lyrics_transcriber/frontend/src/validation.ts +0 -132
- lyrics_transcriber/frontend/src/vite-env.d.ts +0 -1
- lyrics_transcriber/frontend/tsconfig.app.json +0 -26
- lyrics_transcriber/frontend/tsconfig.json +0 -25
- lyrics_transcriber/frontend/tsconfig.node.json +0 -23
- lyrics_transcriber/frontend/tsconfig.tsbuildinfo +0 -1
- lyrics_transcriber/frontend/update_version.js +0 -11
- lyrics_transcriber/frontend/vite.config.d.ts +0 -2
- lyrics_transcriber/frontend/vite.config.js +0 -15
- lyrics_transcriber/frontend/vite.config.ts +0 -16
- lyrics_transcriber/frontend/web_assets/android-chrome-192x192.png +0 -0
- lyrics_transcriber/frontend/web_assets/android-chrome-512x512.png +0 -0
- lyrics_transcriber/frontend/web_assets/apple-touch-icon.png +0 -0
- lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js +0 -44465
- lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js.map +0 -1
- lyrics_transcriber/frontend/web_assets/favicon-16x16.png +0 -0
- lyrics_transcriber/frontend/web_assets/favicon-32x32.png +0 -0
- lyrics_transcriber/frontend/web_assets/favicon.ico +0 -0
- lyrics_transcriber/frontend/web_assets/index.html +0 -22
- lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.png +0 -0
- lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.svg +0 -5
- lyrics_transcriber/frontend/yarn.lock +0 -3711
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/apple-touch-icon.png +0 -0
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-16x16.png +0 -0
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-32x32.png +0 -0
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon.ico +0 -0
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/nomad-karaoke-logo.svg +0 -0
- /lyrics_transcriber/frontend/public/nomad-karaoke-logo.png → /karaoke_gen/nextjs_frontend/out/nomad-logo.png +0 -0
- {karaoke_gen-0.103.1.dist-info → karaoke_gen-0.107.0.dist-info}/entry_points.txt +0 -0
- {karaoke_gen-0.103.1.dist-info → karaoke_gen-0.107.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# React + TypeScript + Vite
|
|
2
|
-
|
|
3
|
-
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
4
|
-
|
|
5
|
-
Currently, two official plugins are available:
|
|
6
|
-
|
|
7
|
-
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
|
8
|
-
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
|
9
|
-
|
|
10
|
-
## Expanding the ESLint configuration
|
|
11
|
-
|
|
12
|
-
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
|
13
|
-
|
|
14
|
-
- Configure the top-level `parserOptions` property like this:
|
|
15
|
-
|
|
16
|
-
```js
|
|
17
|
-
export default tseslint.config({
|
|
18
|
-
languageOptions: {
|
|
19
|
-
// other options...
|
|
20
|
-
parserOptions: {
|
|
21
|
-
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
22
|
-
tsconfigRootDir: import.meta.dirname,
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
})
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
|
|
29
|
-
- Optionally add `...tseslint.configs.stylisticTypeChecked`
|
|
30
|
-
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
// eslint.config.js
|
|
34
|
-
import react from 'eslint-plugin-react'
|
|
35
|
-
|
|
36
|
-
export default tseslint.config({
|
|
37
|
-
// Set the react version
|
|
38
|
-
settings: { react: { version: '18.3' } },
|
|
39
|
-
plugins: {
|
|
40
|
-
// Add the react plugin
|
|
41
|
-
react,
|
|
42
|
-
},
|
|
43
|
-
rules: {
|
|
44
|
-
// other rules...
|
|
45
|
-
// Enable its recommended rules
|
|
46
|
-
...react.configs.recommended.rules,
|
|
47
|
-
...react.configs['jsx-runtime'].rules,
|
|
48
|
-
},
|
|
49
|
-
})
|
|
50
|
-
```
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
Please read this doc to understand the "Replace All" modal we implemented in a previous chat: @REPLACE_ALL_FUNCTIONALITY.md
|
|
2
|
-
|
|
3
|
-
The primary code for the new modal is here: @ReplaceAllLyricsModal.tsx
|
|
4
|
-
but the manual sync functionality relies heavily on @EditTimelineSection.tsx, @useManualSync.ts and @EditActionBar.tsx
|
|
5
|
-
|
|
6
|
-
The functionality mostly works but we need to continue refining it and fixing issues until it is good enough for me and other users to use. Please let me know once you've reviewed the above and you're ready for me to explain the first issue.
|
|
7
|
-
|
|
8
|
-
# Replace All Lyrics Functionality
|
|
9
|
-
|
|
10
|
-
## Overview
|
|
11
|
-
|
|
12
|
-
The "Replace All Lyrics" functionality provides a complete solution for replacing transcribed lyrics when the original transcription quality is too poor to edit word-by-word. This feature allows users to start fresh with clipboard content and manually sync timing for the entire song.
|
|
13
|
-
|
|
14
|
-
## Key Components
|
|
15
|
-
|
|
16
|
-
### 1. ReplaceAllLyricsModal.tsx
|
|
17
|
-
- **Location**: `src/components/ReplaceAllLyricsModal.tsx`
|
|
18
|
-
- **Purpose**: Standalone modal for replacing all lyrics with clipboard content
|
|
19
|
-
- **Design**: Separate from EditModal.tsx to maintain clean separation of concerns
|
|
20
|
-
|
|
21
|
-
### 2. Integration Points
|
|
22
|
-
- **useManualSync Hook**: Reuses existing manual sync functionality
|
|
23
|
-
- **AudioPlayer Integration**: Leverages global audio controls and duration
|
|
24
|
-
- **Types**: Uses existing LyricsSegment and Word types
|
|
25
|
-
|
|
26
|
-
## User Workflow
|
|
27
|
-
|
|
28
|
-
### Phase 1: Input
|
|
29
|
-
1. **Open Modal**: Access via "Replace All Lyrics" button/action
|
|
30
|
-
2. **Paste Content**: Large textarea for pasting lyrics from clipboard
|
|
31
|
-
3. **Real-time Feedback**:
|
|
32
|
-
- Line count display
|
|
33
|
-
- Word count display
|
|
34
|
-
- Preview of how content will be parsed
|
|
35
|
-
4. **Validation**: Ensures content is not empty before proceeding
|
|
36
|
-
|
|
37
|
-
### Phase 2: Manual Sync
|
|
38
|
-
1. **Automatic Conversion**: Each line becomes a LyricsSegment, each word becomes a Word object
|
|
39
|
-
2. **Timeline View**:
|
|
40
|
-
- Fixed 30-second zoom window
|
|
41
|
-
- Shows entire song duration (0 to audio duration)
|
|
42
|
-
- Visual indicators for word positions
|
|
43
|
-
3. **Manual Timing**:
|
|
44
|
-
- Spacebar to mark word timings during playback
|
|
45
|
-
- Pause/resume functionality for corrections
|
|
46
|
-
- Real-time progress tracking
|
|
47
|
-
4. **Progress Panel**:
|
|
48
|
-
- Shows all segments with sync status
|
|
49
|
-
- Active segment highlighting (blue)
|
|
50
|
-
- Completed segments (green) with timing display
|
|
51
|
-
- Progress indicators (X/Y words synced)
|
|
52
|
-
- Auto-scroll to follow playback
|
|
53
|
-
|
|
54
|
-
## Technical Implementation
|
|
55
|
-
|
|
56
|
-
### Data Structure
|
|
57
|
-
```typescript
|
|
58
|
-
// Each line becomes a LyricsSegment
|
|
59
|
-
{
|
|
60
|
-
id: string,
|
|
61
|
-
text: string, // Full line text
|
|
62
|
-
start_time: number | null,
|
|
63
|
-
end_time: number | null,
|
|
64
|
-
words: Word[] // Each word in the line
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Each word becomes a Word object
|
|
68
|
-
{
|
|
69
|
-
id: string,
|
|
70
|
-
text: string, // Individual word
|
|
71
|
-
start_time: number | null,
|
|
72
|
-
end_time: number | null,
|
|
73
|
-
confidence: number // Set to 1.0 for manual entries
|
|
74
|
-
}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Modal Layout
|
|
78
|
-
- **Full Browser Width**: Uses `maxWidth={false}` and viewport-based calculations
|
|
79
|
-
- **Split Layout**:
|
|
80
|
-
- Timeline Section: 2/3 width
|
|
81
|
-
- Progress Panel: 1/3 width
|
|
82
|
-
- **Responsive Design**: Adapts to different screen sizes
|
|
83
|
-
|
|
84
|
-
### Audio Integration
|
|
85
|
-
- **Duration Detection**: Uses `window.getAudioDuration()` for accurate song length
|
|
86
|
-
- **Playback Control**: Integrates with existing audio controls
|
|
87
|
-
- **Auto-cleanup**: Stops audio when canceling sync
|
|
88
|
-
|
|
89
|
-
## Key Features Implemented
|
|
90
|
-
|
|
91
|
-
### 1. Stable Timeline View
|
|
92
|
-
- **Fixed Zoom**: Always shows 30-second window
|
|
93
|
-
- **Full Song Range**: Timeline spans 0 to full audio duration
|
|
94
|
-
- **Prevents Zoom Changes**: Disabled during manual sync to maintain consistency
|
|
95
|
-
|
|
96
|
-
### 2. Manual Sync Enhancement
|
|
97
|
-
- **Spacebar Timing**: Press spacebar to mark word timings
|
|
98
|
-
- **Pause/Resume**: Alt+P to pause/resume for corrections
|
|
99
|
-
- **Visual Feedback**:
|
|
100
|
-
- Current word highlighting
|
|
101
|
-
- Spacebar press indication
|
|
102
|
-
- Progress tracking
|
|
103
|
-
|
|
104
|
-
### 3. Progress Tracking
|
|
105
|
-
- **Segment Status**: Visual indicators for sync progress
|
|
106
|
-
- **Real-time Updates**: Timing updates as words are synced
|
|
107
|
-
- **Auto-scroll**: Follows active segment during sync
|
|
108
|
-
- **Completion Status**: Clear visual feedback for completed segments
|
|
109
|
-
|
|
110
|
-
### 4. Error Prevention
|
|
111
|
-
- **Input Validation**: Ensures content exists before proceeding
|
|
112
|
-
- **Safe Navigation**: Proper cleanup when canceling
|
|
113
|
-
- **State Management**: Prevents conflicts with existing edit modals
|
|
114
|
-
|
|
115
|
-
## Bug Fixes Implemented
|
|
116
|
-
|
|
117
|
-
### 1. Manual Sync Issues
|
|
118
|
-
- **Problem**: Sync stopping after first spacebar press
|
|
119
|
-
- **Solution**: Fixed infinite re-renders in useEffect dependencies
|
|
120
|
-
- **Result**: Stable manual sync throughout entire song
|
|
121
|
-
|
|
122
|
-
### 2. Timeline Zoom Problems
|
|
123
|
-
- **Problem**: Timeline zooming to single word duration after sync
|
|
124
|
-
- **Solution**: Fixed timeRange calculation to always use full song duration
|
|
125
|
-
- **Result**: Consistent 30-second view regardless of sync progress
|
|
126
|
-
|
|
127
|
-
### 3. Audio Duration
|
|
128
|
-
- **Problem**: Hardcoded duration fallbacks causing inaccurate timelines
|
|
129
|
-
- **Solution**: Integration with real audio duration from AudioPlayer
|
|
130
|
-
- **Result**: Accurate timeline representation of song length
|
|
131
|
-
|
|
132
|
-
### 4. Keyboard Conflicts
|
|
133
|
-
- **Problem**: Multiple keyboard handlers causing conflicts
|
|
134
|
-
- **Solution**: Proper handler cleanup and event management
|
|
135
|
-
- **Result**: Clean keyboard interaction without conflicts
|
|
136
|
-
|
|
137
|
-
## User Experience Improvements
|
|
138
|
-
|
|
139
|
-
### 1. Visual Feedback
|
|
140
|
-
- **Real-time Counts**: Live word/line counting during input
|
|
141
|
-
- **Progress Indicators**: Clear visual feedback on sync progress
|
|
142
|
-
- **Color Coding**: Blue for active, green for completed segments
|
|
143
|
-
|
|
144
|
-
### 2. Navigation
|
|
145
|
-
- **Auto-scroll**: Automatically follows playback position
|
|
146
|
-
- **Manual Navigation**: Can manually scroll through segments
|
|
147
|
-
- **Status Preservation**: Maintains state during navigation
|
|
148
|
-
|
|
149
|
-
### 3. Error Recovery
|
|
150
|
-
- **Pause/Resume**: Ability to pause and correct timing
|
|
151
|
-
- **Cancel Support**: Safe cancellation with proper cleanup
|
|
152
|
-
- **State Reset**: Clean state management between sessions
|
|
153
|
-
|
|
154
|
-
## Integration with Existing Codebase
|
|
155
|
-
|
|
156
|
-
### 1. Reused Components
|
|
157
|
-
- **useManualSync**: Leverages existing manual sync logic
|
|
158
|
-
- **Timeline Components**: Reuses timeline visualization
|
|
159
|
-
- **Audio Controls**: Integrates with existing audio system
|
|
160
|
-
|
|
161
|
-
### 2. Type Safety
|
|
162
|
-
- **TypeScript**: Fully typed implementation
|
|
163
|
-
- **Consistent Interfaces**: Uses existing type definitions
|
|
164
|
-
- **Validation**: Runtime validation for data integrity
|
|
165
|
-
|
|
166
|
-
### 3. State Management
|
|
167
|
-
- **Isolated State**: Doesn't interfere with existing edit functionality
|
|
168
|
-
- **Clean Separation**: Separate modal for replace vs. edit operations
|
|
169
|
-
- **Proper Cleanup**: Ensures no state leakage between modals
|
|
170
|
-
|
|
171
|
-
## Performance Considerations
|
|
172
|
-
|
|
173
|
-
### 1. Rendering Optimization
|
|
174
|
-
- **Memoization**: Strategic use of React.memo and useCallback
|
|
175
|
-
- **Efficient Updates**: Minimal re-renders during sync
|
|
176
|
-
- **Progressive Loading**: Handles large lyric sets efficiently
|
|
177
|
-
|
|
178
|
-
### 2. Memory Management
|
|
179
|
-
- **Cleanup**: Proper cleanup of event listeners and timers
|
|
180
|
-
- **State Reset**: Clean state management between sessions
|
|
181
|
-
- **Audio Integration**: Efficient audio control integration
|
|
182
|
-
|
|
183
|
-
## Future Enhancement Opportunities
|
|
184
|
-
|
|
185
|
-
### 1. Batch Operations
|
|
186
|
-
- **Multi-line Selection**: Select and sync multiple segments at once
|
|
187
|
-
- **Timing Adjustment**: Bulk timing adjustments
|
|
188
|
-
- **Smart Defaults**: AI-suggested timing based on audio analysis
|
|
189
|
-
|
|
190
|
-
### 2. Import/Export
|
|
191
|
-
- **Format Support**: Support for various lyric file formats
|
|
192
|
-
- **Backup/Restore**: Save and restore sync sessions
|
|
193
|
-
- **Templates**: Predefined timing templates
|
|
194
|
-
|
|
195
|
-
### 3. Advanced Sync
|
|
196
|
-
- **Beat Detection**: Automatic beat-based timing suggestions
|
|
197
|
-
- **Voice Activity**: Audio analysis for timing hints
|
|
198
|
-
- **Collaborative Sync**: Multi-user timing collaboration
|
|
199
|
-
|
|
200
|
-
## Summary
|
|
201
|
-
|
|
202
|
-
The "Replace All Lyrics" functionality provides a comprehensive solution for handling poor-quality transcriptions by:
|
|
203
|
-
|
|
204
|
-
1. **Complete Replacement**: Replaces all existing lyrics with fresh clipboard content
|
|
205
|
-
2. **Manual Control**: Gives users full control over timing through manual sync
|
|
206
|
-
3. **Visual Feedback**: Provides clear progress tracking and status indicators
|
|
207
|
-
4. **Stable Interface**: Maintains consistent timeline view throughout the process
|
|
208
|
-
5. **Clean Integration**: Works seamlessly with existing audio and editing systems
|
|
209
|
-
|
|
210
|
-
This implementation significantly improves the user experience for cases where starting fresh is more efficient than editing individual words, while maintaining the high-quality timing precision needed for karaoke applications.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"""Frontend module for lyrics transcriber web interface."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
# Get the directory containing this file
|
|
6
|
-
__frontend_dir__ = os.path.dirname(os.path.abspath(__file__))
|
|
7
|
-
|
|
8
|
-
def get_frontend_assets_dir():
|
|
9
|
-
"""Get the path to the frontend assets directory.
|
|
10
|
-
|
|
11
|
-
Returns the web_assets directory if it exists (packaged version),
|
|
12
|
-
otherwise returns the dist directory (development version).
|
|
13
|
-
"""
|
|
14
|
-
web_assets_dir = os.path.join(__frontend_dir__, "web_assets")
|
|
15
|
-
dist_dir = os.path.join(__frontend_dir__, "dist")
|
|
16
|
-
|
|
17
|
-
if os.path.exists(web_assets_dir):
|
|
18
|
-
return web_assets_dir
|
|
19
|
-
elif os.path.exists(dist_dir):
|
|
20
|
-
return dist_dir
|
|
21
|
-
else:
|
|
22
|
-
raise FileNotFoundError(
|
|
23
|
-
"Frontend assets not found. Please build the frontend first with: "
|
|
24
|
-
"./scripts/build_frontend.sh"
|
|
25
|
-
)
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
|
|
5
|
-
// Get __dirname equivalent in ESM
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = path.dirname(__filename);
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* E2E tests for the agentic correction workflow in the lyrics transcriber frontend.
|
|
11
|
-
*
|
|
12
|
-
* These tests verify:
|
|
13
|
-
* 1. The UI loads correctly with agentic correction data
|
|
14
|
-
* 2. The AgenticCorrectionMetrics panel displays correctly
|
|
15
|
-
* 3. Corrected words are highlighted and clickable
|
|
16
|
-
* 4. The CorrectionDetailCard shows proper information
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
// Helper function to load fixture data
|
|
20
|
-
async function loadFixtureData(page: import('@playwright/test').Page) {
|
|
21
|
-
const fixturePath = path.join(__dirname, 'fixtures', 'agentic-correction-data.json');
|
|
22
|
-
|
|
23
|
-
// Create a file chooser promise before clicking
|
|
24
|
-
const fileChooserPromise = page.waitForEvent('filechooser');
|
|
25
|
-
|
|
26
|
-
// Click the Load File button
|
|
27
|
-
await page.getByRole('button', { name: /load file/i }).click();
|
|
28
|
-
|
|
29
|
-
// Handle the file chooser
|
|
30
|
-
const fileChooser = await fileChooserPromise;
|
|
31
|
-
await fileChooser.setFiles(fixturePath);
|
|
32
|
-
|
|
33
|
-
// Wait for data to load by asserting expected content appears
|
|
34
|
-
await expect(page.getByText('Hello,')).toBeVisible({ timeout: 5000 });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
test.describe('Agentic Correction Workflow', () => {
|
|
38
|
-
test.beforeEach(async ({ page }) => {
|
|
39
|
-
// Navigate to the app
|
|
40
|
-
await page.goto('/');
|
|
41
|
-
|
|
42
|
-
// Wait for the initial load
|
|
43
|
-
await expect(page.getByText('Lyrics Correction Review')).toBeVisible();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('should load the app in read-only mode', async ({ page }) => {
|
|
47
|
-
// Verify read-only mode alert is shown
|
|
48
|
-
await expect(page.getByText('Running in read-only mode')).toBeVisible();
|
|
49
|
-
|
|
50
|
-
// Verify Load File button is present
|
|
51
|
-
await expect(page.getByRole('button', { name: /load file/i })).toBeVisible();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('should load correction data from JSON file', async ({ page }) => {
|
|
55
|
-
await loadFixtureData(page);
|
|
56
|
-
|
|
57
|
-
// Verify we're no longer in loading state
|
|
58
|
-
await expect(page.getByText('Loading Lyrics Correction Review...')).not.toBeVisible();
|
|
59
|
-
|
|
60
|
-
// Verify expected content from fixture is visible
|
|
61
|
-
await expect(page.getByText('Hello,')).toBeVisible();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test('should render transcription view after loading data', async ({ page }) => {
|
|
65
|
-
await loadFixtureData(page);
|
|
66
|
-
|
|
67
|
-
// Wait for transcription content to render
|
|
68
|
-
await expect(page.getByText('Hello,')).toBeVisible();
|
|
69
|
-
|
|
70
|
-
// Verify the Corrected Transcription header is visible
|
|
71
|
-
await expect(page.getByText('Corrected Transcription')).toBeVisible();
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test.describe('UI Components', () => {
|
|
76
|
-
test('should show Load File button on initial load', async ({ page }) => {
|
|
77
|
-
await page.goto('/');
|
|
78
|
-
|
|
79
|
-
// The Load File button should be visible
|
|
80
|
-
const loadButton = page.getByRole('button', { name: /load file/i });
|
|
81
|
-
await expect(loadButton).toBeVisible();
|
|
82
|
-
|
|
83
|
-
// Should have upload icon
|
|
84
|
-
const uploadIcon = page.locator('svg[data-testid="UploadFileIcon"]');
|
|
85
|
-
await expect(uploadIcon).toBeVisible();
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('should show read-only mode banner', async ({ page }) => {
|
|
89
|
-
await page.goto('/');
|
|
90
|
-
|
|
91
|
-
// The read-only alert should be visible
|
|
92
|
-
await expect(page.getByRole('alert')).toBeVisible();
|
|
93
|
-
await expect(page.getByText(/read-only mode/i)).toBeVisible();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('should have correction metrics component', async ({ page }) => {
|
|
97
|
-
await page.goto('/');
|
|
98
|
-
|
|
99
|
-
// The page structure should be there with Paper components
|
|
100
|
-
const metricsSection = page.locator('.MuiPaper-root');
|
|
101
|
-
await expect(metricsSection.first()).toBeVisible();
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test.describe('File Upload Flow', () => {
|
|
106
|
-
test('should open file dialog when clicking Load File', async ({ page }) => {
|
|
107
|
-
await page.goto('/');
|
|
108
|
-
|
|
109
|
-
// Set up listener for file chooser
|
|
110
|
-
let fileChooserOpened = false;
|
|
111
|
-
page.on('filechooser', () => {
|
|
112
|
-
fileChooserOpened = true;
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Click the button
|
|
116
|
-
const loadButton = page.getByRole('button', { name: /load file/i });
|
|
117
|
-
await loadButton.click();
|
|
118
|
-
|
|
119
|
-
// Wait for the file chooser event to be processed
|
|
120
|
-
await page.waitForEvent('filechooser', { timeout: 5000 }).catch(() => {
|
|
121
|
-
// Event already fired
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Verify file chooser was triggered
|
|
125
|
-
expect(fileChooserOpened).toBe(true);
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test.describe('Review Mode', () => {
|
|
130
|
-
test.beforeEach(async ({ page }) => {
|
|
131
|
-
await page.goto('/');
|
|
132
|
-
await expect(page.getByText('Lyrics Correction Review')).toBeVisible();
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
test('should show Review Mode toggle when agentic data is loaded', async ({ page }) => {
|
|
136
|
-
await loadFixtureData(page);
|
|
137
|
-
|
|
138
|
-
// Wait for content to load
|
|
139
|
-
await expect(page.getByText('Hello,')).toBeVisible();
|
|
140
|
-
|
|
141
|
-
// The Review Mode toggle should be visible when agentic corrections are present
|
|
142
|
-
// It will appear as "Review Off" chip initially (only in non-read-only mode with agentic data)
|
|
143
|
-
// Note: In read-only mode, the toggle won't appear
|
|
144
|
-
const reviewChip = page.getByText(/Review Off|Review Mode/i);
|
|
145
|
-
const chipCount = await reviewChip.count();
|
|
146
|
-
|
|
147
|
-
// Log for debugging purposes (will show in test output)
|
|
148
|
-
if (chipCount === 0) {
|
|
149
|
-
// Review toggle only shows in edit mode, not read-only mode
|
|
150
|
-
// This is expected behavior when loading files in read-only mode
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
test('should show batch actions panel when Review Mode is enabled', async ({ page }) => {
|
|
155
|
-
await loadFixtureData(page);
|
|
156
|
-
|
|
157
|
-
// Wait for content to load
|
|
158
|
-
await expect(page.getByText('Hello,')).toBeVisible();
|
|
159
|
-
|
|
160
|
-
// Find the Review Mode toggle (only visible in non-read-only mode)
|
|
161
|
-
const reviewToggle = page.getByText(/Review Off/i);
|
|
162
|
-
|
|
163
|
-
if (await reviewToggle.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
164
|
-
await reviewToggle.click();
|
|
165
|
-
|
|
166
|
-
// Wait for the batch actions panel to appear
|
|
167
|
-
await expect(page.getByRole('button', { name: /Accept High Confidence/i })).toBeVisible({ timeout: 5000 });
|
|
168
|
-
await expect(page.getByRole('button', { name: /Accept All/i })).toBeVisible();
|
|
169
|
-
await expect(page.getByRole('button', { name: /Revert All/i })).toBeVisible();
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
test('should render corrected words with original text preview', async ({ page }) => {
|
|
174
|
-
await loadFixtureData(page);
|
|
175
|
-
|
|
176
|
-
// Wait for transcription content to load
|
|
177
|
-
await expect(page.getByText('Hello,')).toBeVisible();
|
|
178
|
-
|
|
179
|
-
// Verify correction-related content is rendered
|
|
180
|
-
// The corrected word "now" should be visible (from fixture: "you're" -> "now")
|
|
181
|
-
await expect(page.getByText('now')).toBeVisible();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
test('should toggle Review Mode on and off', async ({ page }) => {
|
|
185
|
-
await loadFixtureData(page);
|
|
186
|
-
|
|
187
|
-
// Wait for content to load
|
|
188
|
-
await expect(page.getByText('Hello,')).toBeVisible();
|
|
189
|
-
|
|
190
|
-
// Find the Review toggle (only visible in non-read-only mode)
|
|
191
|
-
const reviewOff = page.getByText(/Review Off/i);
|
|
192
|
-
|
|
193
|
-
if (await reviewOff.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
194
|
-
// Click to enable Review Mode
|
|
195
|
-
await reviewOff.click();
|
|
196
|
-
|
|
197
|
-
// Should now show "Review Mode" label (in filled state)
|
|
198
|
-
await expect(page.getByText(/Review Mode/i).first()).toBeVisible();
|
|
199
|
-
|
|
200
|
-
// Click to disable Review Mode
|
|
201
|
-
await page.getByText(/Review Mode/i).first().click();
|
|
202
|
-
|
|
203
|
-
// Should show "Review Off" again
|
|
204
|
-
await expect(page.getByText(/Review Off/i)).toBeVisible();
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
});
|