karaoke-gen 0.105.4__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.
Files changed (322) hide show
  1. backend/api/routes/users.py +14 -3
  2. backend/config.py +3 -0
  3. backend/services/encoding_interface.py +4 -0
  4. backend/services/job_notification_service.py +4 -21
  5. backend/tests/test_job_notification_service.py +24 -58
  6. backend/tests/test_video_worker_orchestrator.py +189 -0
  7. backend/workers/video_worker_orchestrator.py +7 -0
  8. karaoke_gen/instrumental_review/server.py +145 -35
  9. karaoke_gen/nextjs_frontend/__init__.py +98 -0
  10. karaoke_gen/nextjs_frontend/out/404/index.html +1 -0
  11. karaoke_gen/nextjs_frontend/out/404.html +1 -0
  12. karaoke_gen/nextjs_frontend/out/__next.__PAGE__.txt +9 -0
  13. karaoke_gen/nextjs_frontend/out/__next._full.txt +22 -0
  14. karaoke_gen/nextjs_frontend/out/__next._head.txt +8 -0
  15. karaoke_gen/nextjs_frontend/out/__next._index.txt +9 -0
  16. karaoke_gen/nextjs_frontend/out/__next._tree.txt +2 -0
  17. karaoke_gen/nextjs_frontend/out/_next/static/chunks/01a7f8fe40f1ff47.js +1 -0
  18. karaoke_gen/nextjs_frontend/out/_next/static/chunks/112f346e31f991df.js +4 -0
  19. karaoke_gen/nextjs_frontend/out/_next/static/chunks/16d1a4dd9d8a873a.js +3 -0
  20. karaoke_gen/nextjs_frontend/out/_next/static/chunks/1ab85c362b8b0e86.js +9 -0
  21. karaoke_gen/nextjs_frontend/out/_next/static/chunks/247eb132b7f7b574.js +1 -0
  22. karaoke_gen/nextjs_frontend/out/_next/static/chunks/2b80d15cc95e4818.js +1 -0
  23. karaoke_gen/nextjs_frontend/out/_next/static/chunks/32c7eba5cd46c1bc.js +7 -0
  24. karaoke_gen/nextjs_frontend/out/_next/static/chunks/483f26794eae53d0.js +1 -0
  25. karaoke_gen/nextjs_frontend/out/_next/static/chunks/550c3b02e85f196a.js +1 -0
  26. karaoke_gen/nextjs_frontend/out/_next/static/chunks/55c5ade44387bef8.js +1 -0
  27. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5628d92b5893add2.css +1 -0
  28. karaoke_gen/nextjs_frontend/out/_next/static/chunks/56ebf7665e4341c8.js +7 -0
  29. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5997132b61dec430.js +1 -0
  30. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5ea55255bce3eb9e.js +5 -0
  31. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5eda89a57490b3cd.js +1 -0
  32. karaoke_gen/nextjs_frontend/out/_next/static/chunks/692f5d9e0d700c76.js +3 -0
  33. karaoke_gen/nextjs_frontend/out/_next/static/chunks/71d7a05b14f9f0f4.js +1 -0
  34. karaoke_gen/nextjs_frontend/out/_next/static/chunks/81ac355749ef3302.js +1 -0
  35. karaoke_gen/nextjs_frontend/out/_next/static/chunks/95f7e5934dbb0e5d.js +1 -0
  36. karaoke_gen/nextjs_frontend/out/_next/static/chunks/9bce8f19eaa46940.js +1 -0
  37. karaoke_gen/nextjs_frontend/out/_next/static/chunks/a6dad97d9634a72d.js +1 -0
  38. karaoke_gen/nextjs_frontend/out/_next/static/chunks/a9ed54eed3e14c92.js +2 -0
  39. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b35cd41238ecfb17.js +1 -0
  40. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5bc3c3d5ebd49eb.js +1 -0
  41. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5c078c08db5ae32.js +5 -0
  42. karaoke_gen/nextjs_frontend/out/_next/static/chunks/be9c44a178104187.js +1 -0
  43. karaoke_gen/nextjs_frontend/out/_next/static/chunks/c4c840e18cb4861c.js +1 -0
  44. karaoke_gen/nextjs_frontend/out/_next/static/chunks/c645af7d6b65f73e.js +1 -0
  45. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d2c5e2575df784d4.js +1 -0
  46. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d30af02b96d81462.js +1 -0
  47. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d9bdf64f4ec1e9b7.js +7 -0
  48. karaoke_gen/nextjs_frontend/out/_next/static/chunks/dcde6ed684dacd0e.js +5 -0
  49. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e422cbe931246000.js +1 -0
  50. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e483af34fc792d38.js +1 -0
  51. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e57422aad6b897da.js +1 -0
  52. karaoke_gen/nextjs_frontend/out/_next/static/chunks/ef02697fb404726a.js +1 -0
  53. karaoke_gen/nextjs_frontend/out/_next/static/chunks/ff1a16fafef87110.js +1 -0
  54. karaoke_gen/nextjs_frontend/out/_next/static/chunks/turbopack-2d9ca3017a9deedf.js +3 -0
  55. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_buildManifest.js +11 -0
  56. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_clientMiddlewareManifest.json +1 -0
  57. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_ssgManifest.js +1 -0
  58. karaoke_gen/nextjs_frontend/out/_not-found/__next._full.txt +18 -0
  59. karaoke_gen/nextjs_frontend/out/_not-found/__next._head.txt +8 -0
  60. karaoke_gen/nextjs_frontend/out/_not-found/__next._index.txt +9 -0
  61. karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.__PAGE__.txt +5 -0
  62. karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.txt +4 -0
  63. karaoke_gen/nextjs_frontend/out/_not-found/__next._tree.txt +2 -0
  64. karaoke_gen/nextjs_frontend/out/_not-found/index.html +1 -0
  65. karaoke_gen/nextjs_frontend/out/_not-found/index.txt +18 -0
  66. karaoke_gen/nextjs_frontend/out/admin/__next._full.txt +25 -0
  67. karaoke_gen/nextjs_frontend/out/admin/__next._head.txt +8 -0
  68. karaoke_gen/nextjs_frontend/out/admin/__next._index.txt +9 -0
  69. karaoke_gen/nextjs_frontend/out/admin/__next._tree.txt +2 -0
  70. karaoke_gen/nextjs_frontend/out/admin/__next.admin.__PAGE__.txt +9 -0
  71. karaoke_gen/nextjs_frontend/out/admin/__next.admin.txt +7 -0
  72. karaoke_gen/nextjs_frontend/out/admin/beta/__next._full.txt +25 -0
  73. karaoke_gen/nextjs_frontend/out/admin/beta/__next._head.txt +8 -0
  74. karaoke_gen/nextjs_frontend/out/admin/beta/__next._index.txt +9 -0
  75. karaoke_gen/nextjs_frontend/out/admin/beta/__next._tree.txt +2 -0
  76. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.__PAGE__.txt +9 -0
  77. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.txt +4 -0
  78. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.txt +7 -0
  79. karaoke_gen/nextjs_frontend/out/admin/beta/index.html +1 -0
  80. karaoke_gen/nextjs_frontend/out/admin/beta/index.txt +25 -0
  81. karaoke_gen/nextjs_frontend/out/admin/index.html +1 -0
  82. karaoke_gen/nextjs_frontend/out/admin/index.txt +25 -0
  83. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._full.txt +25 -0
  84. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._head.txt +8 -0
  85. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._index.txt +9 -0
  86. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._tree.txt +2 -0
  87. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.__PAGE__.txt +9 -0
  88. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.txt +4 -0
  89. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.txt +7 -0
  90. karaoke_gen/nextjs_frontend/out/admin/jobs/index.html +1 -0
  91. karaoke_gen/nextjs_frontend/out/admin/jobs/index.txt +25 -0
  92. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._full.txt +25 -0
  93. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._head.txt +8 -0
  94. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._index.txt +9 -0
  95. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._tree.txt +2 -0
  96. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.__PAGE__.txt +9 -0
  97. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.txt +4 -0
  98. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.txt +7 -0
  99. karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.html +1 -0
  100. karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.txt +25 -0
  101. karaoke_gen/nextjs_frontend/out/admin/searches/__next._full.txt +25 -0
  102. karaoke_gen/nextjs_frontend/out/admin/searches/__next._head.txt +8 -0
  103. karaoke_gen/nextjs_frontend/out/admin/searches/__next._index.txt +9 -0
  104. karaoke_gen/nextjs_frontend/out/admin/searches/__next._tree.txt +2 -0
  105. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.__PAGE__.txt +9 -0
  106. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.txt +4 -0
  107. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.txt +7 -0
  108. karaoke_gen/nextjs_frontend/out/admin/searches/index.html +1 -0
  109. karaoke_gen/nextjs_frontend/out/admin/searches/index.txt +25 -0
  110. karaoke_gen/nextjs_frontend/out/admin/users/__next._full.txt +25 -0
  111. karaoke_gen/nextjs_frontend/out/admin/users/__next._head.txt +8 -0
  112. karaoke_gen/nextjs_frontend/out/admin/users/__next._index.txt +9 -0
  113. karaoke_gen/nextjs_frontend/out/admin/users/__next._tree.txt +2 -0
  114. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.txt +7 -0
  115. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.__PAGE__.txt +9 -0
  116. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.txt +4 -0
  117. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._full.txt +25 -0
  118. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._head.txt +8 -0
  119. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._index.txt +9 -0
  120. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._tree.txt +2 -0
  121. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.txt +7 -0
  122. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.__PAGE__.txt +9 -0
  123. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.txt +4 -0
  124. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.txt +4 -0
  125. karaoke_gen/nextjs_frontend/out/admin/users/detail/index.html +1 -0
  126. karaoke_gen/nextjs_frontend/out/admin/users/detail/index.txt +25 -0
  127. karaoke_gen/nextjs_frontend/out/admin/users/index.html +1 -0
  128. karaoke_gen/nextjs_frontend/out/admin/users/index.txt +25 -0
  129. karaoke_gen/nextjs_frontend/out/app/__next._full.txt +22 -0
  130. karaoke_gen/nextjs_frontend/out/app/__next._head.txt +8 -0
  131. karaoke_gen/nextjs_frontend/out/app/__next._index.txt +9 -0
  132. karaoke_gen/nextjs_frontend/out/app/__next._tree.txt +2 -0
  133. karaoke_gen/nextjs_frontend/out/app/__next.app.__PAGE__.txt +9 -0
  134. karaoke_gen/nextjs_frontend/out/app/__next.app.txt +4 -0
  135. karaoke_gen/nextjs_frontend/out/app/index.html +1 -0
  136. karaoke_gen/nextjs_frontend/out/app/index.txt +22 -0
  137. karaoke_gen/nextjs_frontend/out/app/jobs/__next._full.txt +19 -0
  138. karaoke_gen/nextjs_frontend/out/app/jobs/__next._head.txt +8 -0
  139. karaoke_gen/nextjs_frontend/out/app/jobs/__next._index.txt +9 -0
  140. karaoke_gen/nextjs_frontend/out/app/jobs/__next._tree.txt +2 -0
  141. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  142. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.txt +4 -0
  143. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.txt +4 -0
  144. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.txt +4 -0
  145. karaoke_gen/nextjs_frontend/out/app/jobs/index.html +1 -0
  146. karaoke_gen/nextjs_frontend/out/app/jobs/index.txt +19 -0
  147. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._full.txt +19 -0
  148. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._head.txt +8 -0
  149. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._index.txt +9 -0
  150. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._tree.txt +2 -0
  151. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  152. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.txt +4 -0
  153. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.txt +4 -0
  154. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.txt +4 -0
  155. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.html +1 -0
  156. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.txt +19 -0
  157. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._full.txt +19 -0
  158. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._head.txt +8 -0
  159. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._index.txt +9 -0
  160. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._tree.txt +2 -0
  161. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  162. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.txt +4 -0
  163. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.txt +4 -0
  164. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.txt +4 -0
  165. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.html +1 -0
  166. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.txt +19 -0
  167. karaoke_gen/nextjs_frontend/out/auth/verify/__next._full.txt +22 -0
  168. karaoke_gen/nextjs_frontend/out/auth/verify/__next._head.txt +8 -0
  169. karaoke_gen/nextjs_frontend/out/auth/verify/__next._index.txt +9 -0
  170. karaoke_gen/nextjs_frontend/out/auth/verify/__next._tree.txt +2 -0
  171. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.txt +4 -0
  172. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.__PAGE__.txt +9 -0
  173. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.txt +4 -0
  174. karaoke_gen/nextjs_frontend/out/auth/verify/index.html +1 -0
  175. karaoke_gen/nextjs_frontend/out/auth/verify/index.txt +22 -0
  176. karaoke_gen/nextjs_frontend/out/index.html +1 -0
  177. karaoke_gen/nextjs_frontend/out/index.txt +22 -0
  178. karaoke_gen/nextjs_frontend/out/manifest.webmanifest +31 -0
  179. karaoke_gen/nextjs_frontend/out/order/success/__next._full.txt +22 -0
  180. karaoke_gen/nextjs_frontend/out/order/success/__next._head.txt +8 -0
  181. karaoke_gen/nextjs_frontend/out/order/success/__next._index.txt +9 -0
  182. karaoke_gen/nextjs_frontend/out/order/success/__next._tree.txt +2 -0
  183. karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.__PAGE__.txt +9 -0
  184. karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.txt +4 -0
  185. karaoke_gen/nextjs_frontend/out/order/success/__next.order.txt +4 -0
  186. karaoke_gen/nextjs_frontend/out/order/success/index.html +1 -0
  187. karaoke_gen/nextjs_frontend/out/order/success/index.txt +22 -0
  188. karaoke_gen/nextjs_frontend/out/payment/success/__next._full.txt +22 -0
  189. karaoke_gen/nextjs_frontend/out/payment/success/__next._head.txt +8 -0
  190. karaoke_gen/nextjs_frontend/out/payment/success/__next._index.txt +9 -0
  191. karaoke_gen/nextjs_frontend/out/payment/success/__next._tree.txt +2 -0
  192. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.__PAGE__.txt +9 -0
  193. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.txt +4 -0
  194. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.txt +4 -0
  195. karaoke_gen/nextjs_frontend/out/payment/success/index.html +1 -0
  196. karaoke_gen/nextjs_frontend/out/payment/success/index.txt +22 -0
  197. karaoke_gen/nextjs_frontend/out/screenshots/email-action_reminder.png +0 -0
  198. karaoke_gen/nextjs_frontend/out/screenshots/email-beta_welcome.png +0 -0
  199. karaoke_gen/nextjs_frontend/out/screenshots/email-job_completion.png +0 -0
  200. karaoke_gen/nextjs_frontend/out/screenshots/example-output.avif +0 -0
  201. karaoke_gen/nextjs_frontend/out/screenshots/homepage-full.png +0 -0
  202. karaoke_gen/nextjs_frontend/out/screenshots/homepage-hero.png +0 -0
  203. karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.avif +0 -0
  204. karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.png +0 -0
  205. karaoke_gen/nextjs_frontend/out/screenshots/job-dashboard.avif +0 -0
  206. karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.avif +0 -0
  207. karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.png +0 -0
  208. karaoke_gen/nextjs_frontend/out/sw.js +183 -0
  209. karaoke_gen/utils/cli_args.py +3 -3
  210. karaoke_gen/utils/gen_cli.py +4 -0
  211. karaoke_gen/utils/remote_cli.py +8 -40
  212. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/METADATA +1 -1
  213. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/RECORD +227 -121
  214. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/WHEEL +1 -1
  215. lyrics_transcriber/correction/agentic/agent.py +83 -60
  216. lyrics_transcriber/correction/anchor_sequence.py +48 -3
  217. lyrics_transcriber/correction/corrector.py +92 -58
  218. lyrics_transcriber/review/server.py +165 -33
  219. lyrics_transcriber/utils/tracing.py +214 -0
  220. karaoke_gen/instrumental_review/static/index.html +0 -1721
  221. lyrics_transcriber/frontend/.gitignore +0 -24
  222. lyrics_transcriber/frontend/.yarn/releases/yarn-4.7.0.cjs +0 -935
  223. lyrics_transcriber/frontend/.yarnrc.yml +0 -3
  224. lyrics_transcriber/frontend/README.md +0 -50
  225. lyrics_transcriber/frontend/REPLACE_ALL_FUNCTIONALITY.md +0 -210
  226. lyrics_transcriber/frontend/__init__.py +0 -25
  227. lyrics_transcriber/frontend/e2e/agentic-corrections.spec.ts +0 -207
  228. lyrics_transcriber/frontend/e2e/fixtures/agentic-correction-data.json +0 -226
  229. lyrics_transcriber/frontend/eslint.config.js +0 -28
  230. lyrics_transcriber/frontend/index.html +0 -22
  231. lyrics_transcriber/frontend/package-lock.json +0 -4553
  232. lyrics_transcriber/frontend/package.json +0 -48
  233. lyrics_transcriber/frontend/playwright.config.ts +0 -69
  234. lyrics_transcriber/frontend/public/android-chrome-192x192.png +0 -0
  235. lyrics_transcriber/frontend/public/android-chrome-512x512.png +0 -0
  236. lyrics_transcriber/frontend/src/App.tsx +0 -243
  237. lyrics_transcriber/frontend/src/api.ts +0 -262
  238. lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx +0 -111
  239. lyrics_transcriber/frontend/src/components/AddLyricsModal.tsx +0 -114
  240. lyrics_transcriber/frontend/src/components/AgenticCorrectionMetrics.tsx +0 -204
  241. lyrics_transcriber/frontend/src/components/AppHeader.tsx +0 -65
  242. lyrics_transcriber/frontend/src/components/AudioPlayer.tsx +0 -180
  243. lyrics_transcriber/frontend/src/components/CorrectedWordWithActions.tsx +0 -175
  244. lyrics_transcriber/frontend/src/components/CorrectionAnnotationModal.tsx +0 -359
  245. lyrics_transcriber/frontend/src/components/CorrectionDetailCard.tsx +0 -281
  246. lyrics_transcriber/frontend/src/components/CorrectionMetrics.tsx +0 -162
  247. lyrics_transcriber/frontend/src/components/DurationTimelineView.tsx +0 -257
  248. lyrics_transcriber/frontend/src/components/EditActionBar.tsx +0 -94
  249. lyrics_transcriber/frontend/src/components/EditModal.tsx +0 -720
  250. lyrics_transcriber/frontend/src/components/EditTimelineSection.tsx +0 -592
  251. lyrics_transcriber/frontend/src/components/EditWordList.tsx +0 -431
  252. lyrics_transcriber/frontend/src/components/FileUpload.tsx +0 -77
  253. lyrics_transcriber/frontend/src/components/FindReplaceModal.tsx +0 -467
  254. lyrics_transcriber/frontend/src/components/Header.tsx +0 -520
  255. lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +0 -1526
  256. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/SyncControls.tsx +0 -216
  257. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/TimelineCanvas.tsx +0 -721
  258. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/UpcomingWordsBar.tsx +0 -80
  259. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/index.tsx +0 -999
  260. lyrics_transcriber/frontend/src/components/MetricsDashboard.tsx +0 -51
  261. lyrics_transcriber/frontend/src/components/ModeSelectionModal.tsx +0 -127
  262. lyrics_transcriber/frontend/src/components/ModeSelector.tsx +0 -67
  263. lyrics_transcriber/frontend/src/components/ModelSelector.tsx +0 -23
  264. lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +0 -177
  265. lyrics_transcriber/frontend/src/components/ReferenceView.tsx +0 -268
  266. lyrics_transcriber/frontend/src/components/ReplaceAllLyricsModal.tsx +0 -336
  267. lyrics_transcriber/frontend/src/components/ReviewChangesModal.tsx +0 -354
  268. lyrics_transcriber/frontend/src/components/SegmentDetailsModal.tsx +0 -64
  269. lyrics_transcriber/frontend/src/components/TimelineEditor.tsx +0 -383
  270. lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +0 -131
  271. lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +0 -266
  272. lyrics_transcriber/frontend/src/components/WordDivider.tsx +0 -191
  273. lyrics_transcriber/frontend/src/components/shared/components/HighlightedText.tsx +0 -466
  274. lyrics_transcriber/frontend/src/components/shared/components/SourceSelector.tsx +0 -56
  275. lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +0 -89
  276. lyrics_transcriber/frontend/src/components/shared/constants.ts +0 -30
  277. lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +0 -180
  278. lyrics_transcriber/frontend/src/components/shared/styles.ts +0 -13
  279. lyrics_transcriber/frontend/src/components/shared/types.js +0 -2
  280. lyrics_transcriber/frontend/src/components/shared/types.ts +0 -135
  281. lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +0 -177
  282. lyrics_transcriber/frontend/src/components/shared/utils/localStorage.ts +0 -78
  283. lyrics_transcriber/frontend/src/components/shared/utils/referenceLineCalculator.ts +0 -75
  284. lyrics_transcriber/frontend/src/components/shared/utils/segmentOperations.ts +0 -360
  285. lyrics_transcriber/frontend/src/components/shared/utils/timingUtils.ts +0 -110
  286. lyrics_transcriber/frontend/src/components/shared/utils/wordUtils.ts +0 -22
  287. lyrics_transcriber/frontend/src/hooks/useManualSync.ts +0 -537
  288. lyrics_transcriber/frontend/src/main.tsx +0 -11
  289. lyrics_transcriber/frontend/src/theme.ts +0 -406
  290. lyrics_transcriber/frontend/src/types/global.d.ts +0 -9
  291. lyrics_transcriber/frontend/src/types.js +0 -2
  292. lyrics_transcriber/frontend/src/types.ts +0 -199
  293. lyrics_transcriber/frontend/src/validation.ts +0 -132
  294. lyrics_transcriber/frontend/src/vite-env.d.ts +0 -1
  295. lyrics_transcriber/frontend/tsconfig.app.json +0 -26
  296. lyrics_transcriber/frontend/tsconfig.json +0 -25
  297. lyrics_transcriber/frontend/tsconfig.node.json +0 -23
  298. lyrics_transcriber/frontend/tsconfig.tsbuildinfo +0 -1
  299. lyrics_transcriber/frontend/update_version.js +0 -11
  300. lyrics_transcriber/frontend/vite.config.d.ts +0 -2
  301. lyrics_transcriber/frontend/vite.config.js +0 -15
  302. lyrics_transcriber/frontend/vite.config.ts +0 -16
  303. lyrics_transcriber/frontend/web_assets/android-chrome-192x192.png +0 -0
  304. lyrics_transcriber/frontend/web_assets/android-chrome-512x512.png +0 -0
  305. lyrics_transcriber/frontend/web_assets/apple-touch-icon.png +0 -0
  306. lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js +0 -44465
  307. lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js.map +0 -1
  308. lyrics_transcriber/frontend/web_assets/favicon-16x16.png +0 -0
  309. lyrics_transcriber/frontend/web_assets/favicon-32x32.png +0 -0
  310. lyrics_transcriber/frontend/web_assets/favicon.ico +0 -0
  311. lyrics_transcriber/frontend/web_assets/index.html +0 -22
  312. lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.png +0 -0
  313. lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.svg +0 -5
  314. lyrics_transcriber/frontend/yarn.lock +0 -3711
  315. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/apple-touch-icon.png +0 -0
  316. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-16x16.png +0 -0
  317. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-32x32.png +0 -0
  318. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon.ico +0 -0
  319. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/nomad-karaoke-logo.svg +0 -0
  320. /lyrics_transcriber/frontend/public/nomad-karaoke-logo.png → /karaoke_gen/nextjs_frontend/out/nomad-logo.png +0 -0
  321. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/entry_points.txt +0 -0
  322. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,180 +0,0 @@
1
- import { useCallback } from 'react'
2
- import { AnchorSequence, GapSequence, InteractionMode, WordCorrection } from '../../../types'
3
- import { ModalContent } from '../../LyricsAnalyzer'
4
- import { WordClickInfo } from '../types'
5
-
6
- export interface UseWordClickProps {
7
- mode: InteractionMode
8
- onElementClick: (content: ModalContent) => void
9
- onWordClick?: (info: WordClickInfo) => void
10
- isReference?: boolean
11
- currentSource?: string
12
- gaps?: GapSequence[]
13
- anchors?: AnchorSequence[]
14
- corrections?: WordCorrection[]
15
- }
16
-
17
- export function useWordClick({
18
- mode,
19
- onElementClick,
20
- onWordClick,
21
- isReference = false,
22
- currentSource = '',
23
- gaps = [],
24
- anchors = [],
25
- corrections = []
26
- }: UseWordClickProps) {
27
- const handleWordClick = useCallback((
28
- word: string,
29
- wordId: string,
30
- anchor?: AnchorSequence,
31
- gap?: GapSequence
32
- ) => {
33
- // Check if word belongs to anchor
34
- const belongsToAnchor = anchor && (
35
- isReference
36
- ? anchor.reference_word_ids[currentSource]?.includes(wordId)
37
- : anchor.transcribed_word_ids.includes(wordId)
38
- )
39
-
40
- // Find matching gap if not provided
41
- const matchingGap = gap || gaps.find(g =>
42
- g.transcribed_word_ids.includes(wordId) ||
43
- Object.values(g.reference_word_ids).some(ids => ids.includes(wordId))
44
- )
45
-
46
- // Check if word belongs to gap - include both original and corrected words
47
- const belongsToGap = matchingGap && (
48
- isReference
49
- ? matchingGap.reference_word_ids[currentSource]?.includes(wordId)
50
- : (matchingGap.transcribed_word_ids.includes(wordId) ||
51
- corrections.some(c =>
52
- c.corrected_word_id === wordId ||
53
- c.word_id === wordId
54
- ))
55
- )
56
-
57
- // Debug info
58
- console.log('Word Click Debug:', {
59
- clickInfo: {
60
- word,
61
- wordId,
62
- isReference,
63
- currentSource,
64
- mode
65
- },
66
- anchorInfo: anchor && {
67
- id: anchor.id,
68
- transcribedWordIds: anchor.transcribed_word_ids,
69
- referenceWordIds: anchor.reference_word_ids,
70
- belongsToAnchor
71
- },
72
- gapInfo: matchingGap && {
73
- id: matchingGap.id,
74
- transcribedWordIds: matchingGap.transcribed_word_ids,
75
- referenceWordIds: matchingGap.reference_word_ids,
76
- belongsToGap,
77
- relatedCorrections: corrections.filter(c =>
78
- matchingGap.transcribed_word_ids.includes(c.word_id) ||
79
- c.corrected_word_id === wordId ||
80
- c.word_id === wordId
81
- )
82
- }
83
- })
84
-
85
- // For reference view clicks, find the corresponding gap
86
- if (isReference && currentSource) {
87
- const matchingGap = gaps?.find(g =>
88
- g.reference_word_ids[currentSource]?.includes(wordId)
89
- )
90
-
91
- if (matchingGap) {
92
- console.log('Found matching gap for reference click:', {
93
- wordId,
94
- gap: matchingGap
95
- })
96
- gap = matchingGap
97
- }
98
- }
99
-
100
- if (mode === 'highlight' || mode === 'edit' || mode === 'delete_word') {
101
- if (belongsToAnchor && anchor) {
102
- onWordClick?.({
103
- word_id: wordId,
104
- type: 'anchor',
105
- anchor,
106
- gap: undefined
107
- })
108
- } else if (belongsToGap && gap) {
109
- onWordClick?.({
110
- word_id: wordId,
111
- type: 'gap',
112
- anchor: undefined,
113
- gap
114
- })
115
- } else if (corrections.some(c =>
116
- (c.corrected_word_id === wordId || c.word_id === wordId) &&
117
- gap?.transcribed_word_ids.includes(c.word_id)
118
- )) {
119
- // If the word is part of a correction, mark it as a gap
120
- onWordClick?.({
121
- word_id: wordId,
122
- type: 'gap',
123
- anchor: undefined,
124
- gap
125
- })
126
- } else {
127
- onWordClick?.({
128
- word_id: wordId,
129
- type: 'other',
130
- anchor: undefined,
131
- gap: undefined
132
- })
133
- }
134
- } else {
135
- // This is a fallback for any future modes
136
- if (belongsToAnchor && anchor) {
137
- onElementClick({
138
- type: 'anchor',
139
- data: {
140
- ...anchor,
141
- wordId,
142
- word,
143
- anchor_sequences: anchors
144
- }
145
- })
146
- } else if (belongsToGap && gap) {
147
- onElementClick({
148
- type: 'gap',
149
- data: {
150
- ...gap,
151
- wordId,
152
- word,
153
- anchor_sequences: anchors
154
- }
155
- })
156
- } else if (!isReference) {
157
- // Create synthetic gap for non-sequence words (transcription view only)
158
- const syntheticGap: GapSequence = {
159
- id: `synthetic-${wordId}`,
160
- transcribed_word_ids: [wordId],
161
- transcription_position: -1,
162
- preceding_anchor_id: null,
163
- following_anchor_id: null,
164
- reference_word_ids: {}
165
- }
166
- onElementClick({
167
- type: 'gap',
168
- data: {
169
- ...syntheticGap,
170
- wordId,
171
- word,
172
- anchor_sequences: anchors
173
- }
174
- })
175
- }
176
- }
177
- }, [mode, onWordClick, onElementClick, isReference, currentSource, gaps, anchors, corrections])
178
-
179
- return { handleWordClick }
180
- }
@@ -1,13 +0,0 @@
1
- import { styled } from '@mui/system'
2
- import { flashAnimation } from './constants'
3
-
4
- export const HighlightedWord = styled('span')<{ shouldFlash: boolean }>(
5
- ({ shouldFlash }) => ({
6
- display: 'inline-block',
7
- marginRight: '0.25em',
8
- transition: 'background-color 0.2s ease',
9
- ...(shouldFlash && {
10
- animation: `${flashAnimation} 0.4s ease-in-out 3`,
11
- }),
12
- })
13
- )
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,135 +0,0 @@
1
- import { AnchorSequence, GapSequence, HighlightInfo, InteractionMode, CorrectionData, LyricsSegment, ReferenceSource, WordCorrection } from '../../types'
2
- import { ModalContent } from '../LyricsAnalyzer'
3
-
4
- // Add FlashType definition directly in shared types
5
- export type FlashType = 'anchor' | 'corrected' | 'uncorrected' | 'word' | 'handler' | null
6
-
7
- // Common word click handling
8
- export interface WordClickInfo {
9
- word_id: string
10
- type: 'anchor' | 'gap' | 'other'
11
- anchor?: AnchorSequence
12
- gap?: GapSequence
13
- }
14
-
15
- // Base props shared between components
16
- export interface BaseViewProps {
17
- onElementClick: (content: ModalContent) => void
18
- onWordClick?: (info: WordClickInfo) => void
19
- flashingType: FlashType
20
- highlightInfo: HighlightInfo | null
21
- mode: InteractionMode
22
- }
23
-
24
- // Base word position interface - remove the word property from here
25
- export interface BaseWordPosition {
26
- type: 'anchor' | 'gap' | 'other'
27
- sequence?: AnchorSequence | GapSequence
28
- }
29
-
30
- // Transcription-specific word position with timing info
31
- export interface TranscriptionWordPosition extends BaseWordPosition {
32
- word: {
33
- id: string
34
- text: string
35
- start_time?: number
36
- end_time?: number
37
- }
38
- type: 'anchor' | 'gap' | 'other'
39
- sequence?: AnchorSequence | GapSequence
40
- isInRange: boolean
41
- isCorrected?: boolean
42
- }
43
-
44
- // Reference-specific word position with simple string word
45
- export interface ReferenceWordPosition extends BaseWordPosition {
46
- index: number
47
- isHighlighted: boolean
48
- word: string // Simple string word for reference view
49
- }
50
-
51
- // Word component props
52
- export interface WordProps {
53
- word: string
54
- shouldFlash: boolean
55
- isAnchor?: boolean
56
- isCorrectedGap?: boolean
57
- isUncorrectedGap?: boolean
58
- isCurrentlyPlaying?: boolean
59
- padding?: string
60
- onClick?: () => void
61
- correction?: {
62
- originalWord: string
63
- handler: string
64
- confidence: number
65
- source: string
66
- reason?: string
67
- } | null
68
- }
69
-
70
- // Text segment props
71
- export interface TextSegmentProps extends BaseViewProps {
72
- wordPositions: TranscriptionWordPosition[] | ReferenceWordPosition[]
73
- }
74
-
75
- // View-specific props
76
- export interface TranscriptionViewProps {
77
- data: CorrectionData
78
- onElementClick: (content: ModalContent) => void
79
- onWordClick?: (info: WordClickInfo) => void
80
- flashingType: FlashType
81
- highlightInfo: HighlightInfo | null
82
- mode: InteractionMode
83
- onPlaySegment?: (startTime: number) => void
84
- currentTime?: number
85
- anchors?: AnchorSequence[]
86
- flashingHandler?: string | null
87
- onDataChange?: (updatedData: CorrectionData) => void
88
- // Review mode props for agentic corrections
89
- reviewMode?: boolean
90
- onRevertCorrection?: (wordId: string) => void
91
- onEditCorrection?: (wordId: string) => void
92
- onAcceptCorrection?: (wordId: string) => void
93
- onShowCorrectionDetail?: (wordId: string) => void
94
- }
95
-
96
- // Add LinePosition type here since it's used in multiple places
97
- export interface LinePosition {
98
- position: number
99
- lineNumber: number
100
- isEmpty?: boolean
101
- }
102
-
103
- // Reference-specific props
104
- export interface ReferenceViewProps extends BaseViewProps {
105
- referenceSources: Record<string, ReferenceSource>
106
- anchors: CorrectionData['anchor_sequences']
107
- gaps: CorrectionData['gap_sequences']
108
- currentSource: string
109
- onSourceChange: (source: string) => void
110
- corrected_segments: LyricsSegment[]
111
- corrections: WordCorrection[]
112
- onAddLyrics?: () => void
113
- }
114
-
115
- // Update HighlightedTextProps to include linePositions
116
- export interface HighlightedTextProps extends BaseViewProps {
117
- text?: string
118
- segments?: LyricsSegment[]
119
- wordPositions: TranscriptionWordPosition[] | ReferenceWordPosition[]
120
- anchors: AnchorSequence[]
121
- highlightInfo: HighlightInfo | null
122
- mode: InteractionMode
123
- onElementClick: (content: ModalContent) => void
124
- onWordClick?: (info: WordClickInfo) => void
125
- flashingType: FlashType
126
- isReference?: boolean
127
- currentSource?: string
128
- preserveSegments?: boolean
129
- linePositions?: LinePosition[]
130
- currentTime?: number
131
- referenceCorrections?: Map<string, string>
132
- gaps?: GapSequence[]
133
- flashingHandler?: string | null
134
- corrections?: WordCorrection[]
135
- }
@@ -1,177 +0,0 @@
1
- // Add a global ref for the modal handler
2
- let currentModalHandler: ((e: KeyboardEvent) => void) | undefined
3
- let isModalOpen = false
4
- const debugLog = false
5
-
6
- type KeyboardState = {
7
- setIsShiftPressed: (value: boolean) => void
8
- setIsCtrlPressed?: (value: boolean) => void
9
- modalHandler?: {
10
- isOpen: boolean
11
- onSpacebar?: (e: KeyboardEvent) => void
12
- }
13
- }
14
-
15
- // Add functions to update the modal handler state
16
- export const setModalHandler = (handler: ((e: KeyboardEvent) => void) | undefined, open: boolean) => {
17
- if (debugLog) {
18
- console.log('setModalHandler called', {
19
- hasHandler: !!handler,
20
- open,
21
- previousState: {
22
- hadHandler: !!currentModalHandler,
23
- wasOpen: isModalOpen
24
- }
25
- })
26
- }
27
-
28
- currentModalHandler = handler
29
- isModalOpen = open
30
- }
31
-
32
- export const setupKeyboardHandlers = (state: KeyboardState) => {
33
- const handlerId = Math.random().toString(36).substr(2, 9)
34
- if (debugLog) {
35
- console.log(`Setting up keyboard handlers [${handlerId}]`)
36
- }
37
-
38
- // Function to reset modifier key states
39
- const resetModifierStates = () => {
40
- if (debugLog) {
41
- console.log(`Resetting modifier states [${handlerId}]`)
42
- }
43
- state.setIsShiftPressed(false)
44
- state.setIsCtrlPressed?.(false)
45
- document.body.style.userSelect = ''
46
- }
47
-
48
- const handleKeyDown = (e: KeyboardEvent) => {
49
- if (debugLog) {
50
- console.log(`Keyboard event captured [${handlerId}]`, {
51
- key: e.key,
52
- code: e.code,
53
- type: e.type,
54
- target: e.target,
55
- currentTarget: e.currentTarget,
56
- eventPhase: e.eventPhase,
57
- isModalOpen,
58
- hasModalHandler: !!currentModalHandler
59
- })
60
- }
61
-
62
- if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
63
- if (debugLog) {
64
- console.log(`[${handlerId}] Ignoring keydown in input/textarea`)
65
- }
66
- return
67
- }
68
-
69
- if (e.key === 'Shift') {
70
- state.setIsShiftPressed(true)
71
- document.body.style.userSelect = 'none'
72
- } else if (e.key === 'Control' || e.key === 'Ctrl' || e.key === 'Meta') {
73
- state.setIsCtrlPressed?.(true)
74
- } else if (e.key === ' ' || e.code === 'Space') {
75
- if (debugLog) {
76
- console.log('Keyboard handler - Spacebar pressed down', {
77
- modalOpen: isModalOpen,
78
- hasModalHandler: !!currentModalHandler,
79
- hasGlobalToggle: !!window.toggleAudioPlayback,
80
- target: e.target,
81
- eventPhase: e.eventPhase,
82
- handlerFunction: currentModalHandler?.toString().slice(0, 100)
83
- })
84
- }
85
-
86
- e.preventDefault()
87
-
88
- if (isModalOpen && currentModalHandler) {
89
- currentModalHandler(e)
90
- } else if (window.toggleAudioPlayback && !isModalOpen) {
91
- if (debugLog) {
92
- console.log('Keyboard handler - Using global audio toggle')
93
- }
94
- window.toggleAudioPlayback()
95
- }
96
- }
97
- }
98
-
99
- const handleKeyUp = (e: KeyboardEvent) => {
100
- if (debugLog) {
101
- console.log(`Keyboard up event captured [${handlerId}]`, {
102
- key: e.key,
103
- code: e.code,
104
- type: e.type,
105
- target: e.target,
106
- eventPhase: e.eventPhase,
107
- isModalOpen,
108
- hasModalHandler: !!currentModalHandler
109
- })
110
- }
111
-
112
- // Ignore keyup events in input and textarea elements
113
- if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
114
- if (debugLog) {
115
- console.log(`[${handlerId}] Ignoring keyup in input/textarea`)
116
- }
117
- return
118
- }
119
-
120
- // Always reset the modifier states regardless of the key which was released
121
- // to help prevent accidentally getting stuck in a mode or accidentally deleting words
122
- resetModifierStates()
123
-
124
- if (e.key === ' ' || e.code === 'Space') {
125
- if (debugLog) {
126
- console.log('Keyboard handler - Spacebar released', {
127
- modalOpen: isModalOpen,
128
- hasModalHandler: !!currentModalHandler,
129
- target: e.target,
130
- eventPhase: e.eventPhase
131
- })
132
- }
133
-
134
- e.preventDefault()
135
-
136
- if (isModalOpen && currentModalHandler) {
137
- currentModalHandler(e)
138
- }
139
- }
140
- }
141
-
142
- // Handle window blur event (user switches tabs or apps)
143
- const handleWindowBlur = () => {
144
- if (debugLog) {
145
- console.log(`Window blur detected [${handlerId}], resetting modifier states`)
146
- }
147
- resetModifierStates()
148
- }
149
-
150
- // Handle window focus event (user returns to the app)
151
- const handleWindowFocus = () => {
152
- if (debugLog) {
153
- console.log(`Window focus detected [${handlerId}], ensuring modifier states are reset`)
154
- }
155
- resetModifierStates()
156
- }
157
-
158
- // Add window event listeners
159
- window.addEventListener('blur', handleWindowBlur)
160
- window.addEventListener('focus', handleWindowFocus)
161
-
162
- // Return a cleanup function that includes removing the window event listeners
163
- return {
164
- handleKeyDown,
165
- handleKeyUp,
166
- cleanup: () => {
167
- window.removeEventListener('blur', handleWindowBlur)
168
- window.removeEventListener('focus', handleWindowFocus)
169
- }
170
- }
171
- }
172
-
173
- // Export these for external use
174
- export const getModalState = () => ({
175
- currentModalHandler,
176
- isModalOpen
177
- })
@@ -1,78 +0,0 @@
1
- import { CorrectionData, LyricsSegment } from '../../../types'
2
-
3
- // Change the key generation to use a hash of the first segment's text instead
4
- export const generateStorageKey = (data: CorrectionData): string => {
5
- const text = data.original_segments[0]?.text || ''
6
- let hash = 0
7
- for (let i = 0; i < text.length; i++) {
8
- const char = text.charCodeAt(i)
9
- hash = ((hash << 5) - hash) + char
10
- hash = hash & hash // Convert to 32-bit integer
11
- }
12
- return `song_${hash}`
13
- }
14
-
15
- const stripIds = (obj: CorrectionData): LyricsSegment[] => {
16
- const clone = JSON.parse(JSON.stringify(obj))
17
- return clone.corrected_segments.map((segment: LyricsSegment) => {
18
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
19
- const { id: _id, ...strippedSegment } = segment
20
- return {
21
- ...strippedSegment,
22
- words: segment.words.map(word => {
23
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
24
- const { id: _wordId, ...strippedWord } = word
25
- return strippedWord
26
- })
27
- }
28
- })
29
- }
30
-
31
- export const loadSavedData = (initialData: CorrectionData): CorrectionData | null => {
32
- const storageKey = generateStorageKey(initialData)
33
- const savedDataStr = localStorage.getItem('lyrics_analyzer_data')
34
- const savedDataObj = savedDataStr ? JSON.parse(savedDataStr) : {}
35
-
36
- if (savedDataObj[storageKey]) {
37
- try {
38
- const parsed = savedDataObj[storageKey]
39
- // Compare first segment text instead of transcribed_text
40
- if (parsed.original_segments[0]?.text === initialData.original_segments[0]?.text) {
41
- const strippedSaved = stripIds(parsed)
42
- const strippedInitial = stripIds(initialData)
43
- const hasChanges = JSON.stringify(strippedSaved) !== JSON.stringify(strippedInitial)
44
-
45
- if (hasChanges) {
46
- return parsed
47
- } else {
48
- // Clean up storage if no changes
49
- delete savedDataObj[storageKey]
50
- localStorage.setItem('lyrics_analyzer_data', JSON.stringify(savedDataObj))
51
- }
52
- }
53
- } catch (error) {
54
- console.error('Failed to parse saved data:', error)
55
- delete savedDataObj[storageKey]
56
- localStorage.setItem('lyrics_analyzer_data', JSON.stringify(savedDataObj))
57
- }
58
- }
59
- return null
60
- }
61
-
62
- export const saveData = (data: CorrectionData, initialData: CorrectionData): void => {
63
- const storageKey = generateStorageKey(initialData)
64
- const savedDataStr = localStorage.getItem('lyrics_analyzer_data')
65
- const savedDataObj = savedDataStr ? JSON.parse(savedDataStr) : {}
66
-
67
- savedDataObj[storageKey] = data
68
- localStorage.setItem('lyrics_analyzer_data', JSON.stringify(savedDataObj))
69
- }
70
-
71
- export const clearSavedData = (data: CorrectionData): void => {
72
- const storageKey = generateStorageKey(data)
73
- const savedDataStr = localStorage.getItem('lyrics_analyzer_data')
74
- const savedDataObj = savedDataStr ? JSON.parse(savedDataStr) : {}
75
-
76
- delete savedDataObj[storageKey]
77
- localStorage.setItem('lyrics_analyzer_data', JSON.stringify(savedDataObj))
78
- }
@@ -1,75 +0,0 @@
1
- import { AnchorSequence, LyricsSegment } from '../../../types'
2
- import { LinePosition } from '../types'
3
-
4
- export function calculateReferenceLinePositions(
5
- corrected_segments: LyricsSegment[],
6
- anchors: AnchorSequence[],
7
- currentSource: string
8
- ): { linePositions: LinePosition[] } {
9
- const linePositions: LinePosition[] = []
10
- let currentReferencePosition = 0
11
-
12
- // First, find all anchor sequences that cover entire lines
13
- const fullLineAnchors = anchors?.map(anchor => {
14
- // Check if we have reference word IDs for this source
15
- const referenceWordIds = anchor.reference_word_ids[currentSource]
16
- if (!referenceWordIds?.length) return null
17
-
18
- return {
19
- referenceWordIds,
20
- transcriptionLine: corrected_segments.findIndex((segment) => {
21
- const wordIds = segment.words.map(w => w.id)
22
- if (!wordIds.length) return false
23
-
24
- // Check if all word IDs in this segment are part of the anchor's transcribed word IDs
25
- return wordIds.every(id =>
26
- anchor.transcribed_word_ids.includes(id)
27
- )
28
- })
29
- }
30
- })?.filter((a): a is NonNullable<typeof a> => a !== null) ?? []
31
-
32
- // Sort by first reference word ID to process in order
33
- fullLineAnchors.sort((a, b) => {
34
- const firstIdA = a.referenceWordIds[0]
35
- const firstIdB = b.referenceWordIds[0]
36
- return firstIdA.localeCompare(firstIdB)
37
- })
38
-
39
- // Add line positions with padding
40
- let currentLine = 0
41
- fullLineAnchors.forEach(anchor => {
42
- // Add empty lines if needed to match transcription line number
43
- while (currentLine < anchor.transcriptionLine) {
44
- linePositions.push({
45
- position: currentReferencePosition,
46
- lineNumber: currentLine,
47
- isEmpty: false
48
- })
49
- currentReferencePosition += 1
50
- currentLine++
51
- }
52
-
53
- // Add the actual line position
54
- linePositions.push({
55
- position: currentReferencePosition,
56
- lineNumber: currentLine,
57
- isEmpty: false
58
- })
59
- currentLine++
60
- currentReferencePosition++
61
- })
62
-
63
- // Add any remaining lines after the last anchor
64
- while (currentLine < corrected_segments.length) {
65
- linePositions.push({
66
- position: currentReferencePosition,
67
- lineNumber: currentLine,
68
- isEmpty: false
69
- })
70
- currentReferencePosition += 1
71
- currentLine++
72
- }
73
-
74
- return { linePositions }
75
- }