vibefast-cli 1.1.3 → 1.2.1

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 (300) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +63 -169
  3. package/dist/__tests__/recipes.test.js +25 -3
  4. package/dist/__tests__/recipes.test.js.map +1 -1
  5. package/dist/commands/add.d.ts +1 -1
  6. package/dist/commands/add.d.ts.map +1 -1
  7. package/dist/commands/add.js +547 -543
  8. package/dist/commands/add.js.map +1 -1
  9. package/dist/commands/checklist.d.ts +1 -1
  10. package/dist/commands/checklist.d.ts.map +1 -1
  11. package/dist/commands/checklist.js +40 -39
  12. package/dist/commands/checklist.js.map +1 -1
  13. package/dist/commands/doctor.d.ts +1 -1
  14. package/dist/commands/doctor.js +22 -22
  15. package/dist/commands/doctor.js.map +1 -1
  16. package/dist/commands/env.d.ts +1 -1
  17. package/dist/commands/env.d.ts.map +1 -1
  18. package/dist/commands/env.js +58 -53
  19. package/dist/commands/env.js.map +1 -1
  20. package/dist/commands/health.d.ts +1 -1
  21. package/dist/commands/health.d.ts.map +1 -1
  22. package/dist/commands/health.js +101 -93
  23. package/dist/commands/health.js.map +1 -1
  24. package/dist/commands/init.d.ts +1 -1
  25. package/dist/commands/init.d.ts.map +1 -1
  26. package/dist/commands/init.js +416 -296
  27. package/dist/commands/init.js.map +1 -1
  28. package/dist/commands/remove.d.ts +1 -1
  29. package/dist/commands/remove.d.ts.map +1 -1
  30. package/dist/commands/remove.js +77 -64
  31. package/dist/commands/remove.js.map +1 -1
  32. package/dist/commands/status.d.ts +1 -1
  33. package/dist/commands/status.d.ts.map +1 -1
  34. package/dist/commands/status.js +15 -14
  35. package/dist/commands/status.js.map +1 -1
  36. package/dist/core/__tests__/detect.test.js +68 -34
  37. package/dist/core/__tests__/detect.test.js.map +1 -1
  38. package/dist/core/ast.d.ts +14 -0
  39. package/dist/core/ast.d.ts.map +1 -0
  40. package/dist/core/ast.js +239 -0
  41. package/dist/core/ast.js.map +1 -0
  42. package/dist/core/codemod.d.ts.map +1 -1
  43. package/dist/core/codemod.js +62 -44
  44. package/dist/core/codemod.js.map +1 -1
  45. package/dist/core/config.d.ts +10 -0
  46. package/dist/core/config.d.ts.map +1 -0
  47. package/dist/core/config.js +51 -0
  48. package/dist/core/config.js.map +1 -0
  49. package/dist/core/detect.d.ts +8 -2
  50. package/dist/core/detect.d.ts.map +1 -1
  51. package/dist/core/detect.js +52 -21
  52. package/dist/core/detect.js.map +1 -1
  53. package/dist/core/errors.d.ts.map +1 -1
  54. package/dist/core/errors.js +9 -8
  55. package/dist/core/errors.js.map +1 -1
  56. package/dist/core/exec.d.ts +16 -0
  57. package/dist/core/exec.d.ts.map +1 -0
  58. package/dist/core/exec.js +48 -0
  59. package/dist/core/exec.js.map +1 -0
  60. package/dist/core/manualSteps.d.ts +7 -0
  61. package/dist/core/manualSteps.d.ts.map +1 -0
  62. package/dist/core/manualSteps.js +59 -0
  63. package/dist/core/manualSteps.js.map +1 -0
  64. package/dist/core/paths.d.ts +3 -1
  65. package/dist/core/paths.d.ts.map +1 -1
  66. package/dist/core/paths.js +14 -10
  67. package/dist/core/paths.js.map +1 -1
  68. package/dist/core/spinner.d.ts +1 -1
  69. package/dist/core/spinner.d.ts.map +1 -1
  70. package/dist/core/spinner.js +38 -8
  71. package/dist/core/spinner.js.map +1 -1
  72. package/dist/core/vosk.d.ts.map +1 -1
  73. package/dist/core/vosk.js +50 -39
  74. package/dist/core/vosk.js.map +1 -1
  75. package/docs/manual-testing.md +91 -0
  76. package/package.json +6 -3
  77. package/recipes/audio-recorder/apps/native/src/app/audio-recorder/index.tsx +5 -0
  78. package/recipes/audio-recorder/recipe.json +3 -3
  79. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-player.tsx +301 -0
  80. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +373 -0
  81. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-waveform.tsx +270 -0
  82. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/index.ts +4 -0
  83. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/recording-list.tsx +89 -0
  84. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-player-demo.tsx +66 -0
  85. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-cloud.tsx +68 -0
  86. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-interview.tsx +102 -0
  87. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/basic.tsx +27 -0
  88. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/index.ts +5 -0
  89. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +82 -0
  90. package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +369 -0
  91. package/recipes/audio-recorder-supabase/packages/backend/supabase/migrations/recordings.sql +70 -0
  92. package/recipes/audio-recorder-supabase/recipe.json +35 -0
  93. package/recipes/audio-recorder-supabase@latest.zip +0 -0
  94. package/recipes/audio-recorder@latest.zip +0 -0
  95. package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -3
  96. package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +2 -2
  97. package/recipes/charts/apps/native/src/features/charts/components/chart-card.tsx +5 -5
  98. package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -3
  99. package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +20 -4
  100. package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +7 -6
  101. package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +6 -4
  102. package/recipes/charts/apps/native/src/features/charts/components/radial-bar-chart.tsx +1 -1
  103. package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +5 -4
  104. package/recipes/charts/recipe.json +4 -13
  105. package/recipes/charts@latest.zip +0 -0
  106. package/recipes/chatbot/apps/native/src/app/chatbot/index.tsx +1 -0
  107. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +86 -86
  108. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +86 -53
  109. package/recipes/chatbot/recipe.json +26 -92
  110. package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +515 -0
  111. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/app/index.tsx +257 -0
  112. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +59 -0
  113. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-input-bar.tsx +485 -0
  114. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +575 -0
  115. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +223 -0
  116. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +161 -0
  117. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/image-preview-list.tsx +116 -0
  118. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +165 -0
  119. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/index.ts +10 -0
  120. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +129 -0
  121. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-error-boundary.tsx +78 -0
  122. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-list.tsx +170 -0
  123. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/model-selector.tsx +283 -0
  124. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/report-content-modal.tsx +188 -0
  125. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/suggested-messages.tsx +67 -0
  126. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/models.ts +20 -0
  127. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/report-reasons.ts +9 -0
  128. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +142 -0
  129. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-config.ts +458 -0
  130. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +429 -0
  131. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +89 -0
  132. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-conversation.ts +90 -0
  133. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-image-picker.ts +122 -0
  134. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +161 -0
  135. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +213 -0
  136. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/index.ts +86 -0
  137. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/models.ts +162 -0
  138. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/providers.ts +62 -0
  139. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/types.ts +40 -0
  140. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/file-uploader.ts +287 -0
  141. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/message-handler-service.ts +189 -0
  142. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/types/index.ts +70 -0
  143. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/utils/chat-telemetry.ts +91 -0
  144. package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +243 -0
  145. package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +327 -0
  146. package/recipes/chatbot-supabase/packages/backend/supabase/functions/chat-stream/index.ts +347 -0
  147. package/recipes/chatbot-supabase/packages/backend/supabase/migrations/chatbot.sql +104 -0
  148. package/recipes/chatbot-supabase/recipe.json +79 -0
  149. package/recipes/chatbot-supabase@latest.zip +0 -0
  150. package/recipes/chatbot.zip +0 -0
  151. package/recipes/chatbot@latest.zip +0 -0
  152. package/recipes/image-analysis/packages/backend/convex/imageAnalysis/index.ts +2 -2
  153. package/recipes/image-analysis/packages/backend/convex/{imageAnalysisFunctions.ts → imageAnalysis.ts} +5 -5
  154. package/recipes/image-analysis/recipe.json +15 -55
  155. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +304 -0
  156. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/camera.tsx +221 -0
  157. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +333 -0
  158. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading-screen.tsx +214 -0
  159. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading.tsx +191 -0
  160. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/results.tsx +137 -0
  161. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/trait-details.tsx +172 -0
  162. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-analysis-data.ts +160 -0
  163. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-results-screen.ts +151 -0
  164. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-badge.tsx +77 -0
  165. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-card.tsx +75 -0
  166. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-unlocked-modal.tsx +162 -0
  167. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievements-section.tsx +44 -0
  168. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/advice-list.tsx +42 -0
  169. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/circular-progress.tsx +233 -0
  170. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/content-card.tsx +38 -0
  171. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/error-state.tsx +42 -0
  172. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/index.ts +9 -0
  173. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/loading-state.tsx +26 -0
  174. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/profile-image.tsx +60 -0
  175. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/results-header.tsx +62 -0
  176. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/score-display.tsx +54 -0
  177. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/share-options-modal.tsx +110 -0
  178. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/traits-grid.tsx +74 -0
  179. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/analysis-config.ts +80 -0
  180. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/master-analysis-config.ts +157 -0
  181. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/index.ts +1 -0
  182. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-analysis.ts +38 -0
  183. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +208 -0
  184. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/analysis-service.ts +262 -0
  185. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/share-service.ts +176 -0
  186. package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/trait-details-service.ts +289 -0
  187. package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +132 -0
  188. package/recipes/image-analysis-supabase/packages/backend/supabase/functions/analyze-image/index.ts +312 -0
  189. package/recipes/image-analysis-supabase/packages/backend/supabase/migrations/image_analysis.sql +42 -0
  190. package/recipes/image-analysis-supabase/recipe.json +57 -0
  191. package/recipes/image-analysis-supabase@latest.zip +0 -0
  192. package/recipes/image-analysis@latest.zip +0 -0
  193. package/recipes/image-generator/apps/native/src/features/image-generator/app/index.tsx +16 -2
  194. package/recipes/image-generator/apps/native/src/features/image-generator/components/image-model-selector.tsx +11 -5
  195. package/recipes/image-generator/apps/native/src/features/image-generator/hooks/use-image-generator.ts +11 -5
  196. package/recipes/image-generator/packages/backend/convex/imageGeneration/index.ts +2 -2
  197. package/recipes/image-generator/recipe.json +16 -39
  198. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/_layout.tsx +26 -0
  199. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/gallery.tsx +217 -0
  200. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/index.tsx +251 -0
  201. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/gallery-image.tsx +25 -0
  202. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-detail-modal.tsx +215 -0
  203. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-model-selector.tsx +216 -0
  204. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-placeholder.tsx +26 -0
  205. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-gallery.ts +71 -0
  206. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator-settings.ts +152 -0
  207. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator.ts +103 -0
  208. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/models/models.ts +66 -0
  209. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-gallery-service.ts +96 -0
  210. package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-save-service.ts +120 -0
  211. package/recipes/image-generator-supabase/packages/backend/supabase/functions/generate-image/index.ts +291 -0
  212. package/recipes/image-generator-supabase/packages/backend/supabase/migrations/image_generator.sql +71 -0
  213. package/recipes/image-generator-supabase/recipe.json +59 -0
  214. package/recipes/image-generator-supabase@latest.zip +0 -0
  215. package/recipes/image-generator@latest.zip +0 -0
  216. package/recipes/ios-widget/recipe.json +15 -24
  217. package/recipes/ios-widget@latest.zip +0 -0
  218. package/recipes/onboarding/apps/native/src/features/onboarding/analytics/index.ts +9 -0
  219. package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding-with-analytics.tsx +141 -0
  220. package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding.tsx +173 -0
  221. package/recipes/onboarding/apps/native/src/features/onboarding/config/onboarding-flow-config.ts +189 -0
  222. package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/app/index.tsx +42 -0
  223. package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/data.ts +32 -0
  224. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/app/index.tsx +43 -0
  225. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +222 -0
  226. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +133 -0
  227. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +165 -0
  228. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +199 -0
  229. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +154 -0
  230. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +156 -0
  231. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +158 -0
  232. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +139 -0
  233. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +129 -0
  234. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +138 -0
  235. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +190 -0
  236. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +98 -0
  237. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +181 -0
  238. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +110 -0
  239. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +139 -0
  240. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +217 -0
  241. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +58 -0
  242. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/constants.ts +179 -0
  243. package/recipes/onboarding/apps/native/src/features/onboarding/hooks/use-onboarding-analytics.ts +323 -0
  244. package/recipes/onboarding/apps/native/src/features/onboarding/services/onboarding-analytics.ts +432 -0
  245. package/recipes/onboarding/recipe.json +15 -0
  246. package/recipes/onboarding@latest.zip +0 -0
  247. package/recipes/payments/recipe.json +28 -61
  248. package/recipes/payments-supabase/apps/native/src/features/payments/README.md +200 -0
  249. package/recipes/payments-supabase/apps/native/src/features/payments/app/local-paywall.tsx +194 -0
  250. package/recipes/payments-supabase/apps/native/src/features/payments/app/remote-paywall.tsx +79 -0
  251. package/recipes/payments-supabase/apps/native/src/features/payments/components/payment-initializer.tsx +95 -0
  252. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-error-state.tsx +60 -0
  253. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-local-mode.tsx +116 -0
  254. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-product-card.tsx +133 -0
  255. package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-remote-mode.tsx +146 -0
  256. package/recipes/payments-supabase/apps/native/src/features/payments/hooks/use-entitlement.ts +63 -0
  257. package/recipes/payments-supabase/apps/native/src/features/payments/index.ts +8 -0
  258. package/recipes/payments-supabase/apps/native/src/features/payments/services/revenuecat-adapter.ts +407 -0
  259. package/recipes/payments-supabase/packages/backend/src/services/payments.ts +201 -0
  260. package/recipes/payments-supabase/packages/backend/supabase/migrations/payments.sql +35 -0
  261. package/recipes/payments-supabase/recipe.json +51 -0
  262. package/recipes/payments-supabase@latest.zip +0 -0
  263. package/recipes/payments@latest.zip +0 -0
  264. package/recipes/quiz/apps/native/src/features/quiz/index.tsx +1 -2
  265. package/recipes/quiz/recipe.json +6 -9
  266. package/recipes/quiz@latest.zip +0 -0
  267. package/recipes/tracker-app/apps/native/src/features/tracker-app/app/index.tsx +1 -2
  268. package/recipes/tracker-app/recipe.json +7 -10
  269. package/recipes/tracker-app@latest.zip +0 -0
  270. package/recipes/voice-bot/recipe.json +8 -68
  271. package/recipes/voice-bot.zip +0 -0
  272. package/recipes/voice-bot@latest.zip +0 -0
  273. package/recipes/wake-word/recipe.json +10 -9
  274. package/recipes/wake-word.zip +0 -0
  275. package/recipes/wake-word@latest.zip +0 -0
  276. package/recipes/charts/apps/native/src/app/(root)/(protected)/charts/index.tsx +0 -3
  277. package/recipes/chatbot/packages/backend/convex/lib/rateLimit.ts +0 -100
  278. package/recipes/chatbot/packages/backend/convex/lib/telemetry.ts +0 -29
  279. package/recipes/chatbot/packages/backend/convex/ragKnowledge.ts +0 -0
  280. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/front.jpg +0 -0
  281. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/side.jpg +0 -0
  282. package/recipes/image-analysis/apps/native/assets/features/image-analyzer/threeQuarter.jpg +0 -0
  283. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/_layout.tsx +0 -5
  284. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/analysis-options.tsx +0 -50
  285. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/camera.tsx +0 -2
  286. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/index.tsx +0 -50
  287. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/loading.tsx +0 -50
  288. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/results.tsx +0 -2
  289. package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/trait-details.tsx +0 -3
  290. package/recipes/image-analysis/packages/backend/convex/lib/ai/imageAnalysisAdapter.ts +0 -200
  291. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/index.tsx +0 -74
  292. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/local.tsx +0 -25
  293. package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/remote.tsx +0 -23
  294. package/recipes/quiz/apps/native/src/app/(root)/(protected)/quiz/index.tsx +0 -47
  295. package/recipes/tracker-app/apps/native/src/app/(root)/(protected)/tracker-app/index.tsx +0 -1
  296. package/recipes/voice-bot/apps/native/src/app/(root)/(protected)/voice-bot/index.tsx +0 -27
  297. package/recipes/voice-bot/packages/backend/convex/router.ts +0 -81
  298. /package/recipes/{chatbot/apps/native/src/app/(root)/(protected) → chatbot-supabase/apps/native/src/app}/chatbot/index.tsx +0 -0
  299. /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/gallery.tsx +0 -0
  300. /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/index.tsx +0 -0
package/dist/core/vosk.js CHANGED
@@ -1,31 +1,33 @@
1
- import { appendFileSync, createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, unlinkSync, } from 'fs';
2
- import https from 'https';
3
- import { join, resolve } from 'path';
4
- import { log } from './log.js';
5
- import { extractZipSafe } from './archive.js';
6
- import { execSync } from 'child_process';
7
- const MODEL_URL = 'https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip';
8
- const MODEL_NAME = 'model-en-us';
1
+ import { appendFileSync, createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, unlinkSync, } from "fs";
2
+ import https from "https";
3
+ import { join, resolve } from "path";
4
+ import { log } from "./log.js";
5
+ import { extractZipSafe } from "./archive.js";
6
+ import { spawnSync } from "child_process";
7
+ const MODEL_URL = "https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip";
8
+ const MODEL_NAME = "model-en-us";
9
9
  /**
10
10
  * Download and setup Vosk model for wake-word detection
11
11
  */
12
12
  export async function setupVoskModel(projectRoot, options) {
13
- const ASSETS_DIR = resolve(projectRoot, 'apps/native/assets/vosk-model');
14
- const LEGACY_DIR = resolve(projectRoot, 'assets/vosk-model');
13
+ const ASSETS_DIR = resolve(projectRoot, "apps/native/assets/vosk-model");
14
+ const LEGACY_DIR = resolve(projectRoot, "assets/vosk-model");
15
15
  const MODEL_PATH = join(ASSETS_DIR, MODEL_NAME);
16
16
  const LEGACY_MODEL_PATH = join(LEGACY_DIR, MODEL_NAME);
17
- const ZIP_PATH = join(ASSETS_DIR, 'model.zip');
18
- const GITIGNORE_PATH = resolve(projectRoot, '.gitignore');
17
+ const ZIP_PATH = join(ASSETS_DIR, "model.zip");
18
+ const GITIGNORE_PATH = resolve(projectRoot, ".gitignore");
19
19
  const ensureGitignoreEntry = () => {
20
- const entry = 'assets/vosk-model/model-en-us';
21
- let content = '';
20
+ const entry = "apps/native/assets/vosk-model/model-en-us";
21
+ let content = "";
22
22
  if (existsSync(GITIGNORE_PATH)) {
23
- content = readFileSync(GITIGNORE_PATH, 'utf8');
24
- const hasEntry = content.split(/\r?\n/).some((line) => line.trim() === entry);
23
+ content = readFileSync(GITIGNORE_PATH, "utf8");
24
+ const hasEntry = content
25
+ .split(/\r?\n/)
26
+ .some((line) => line.trim() === entry);
25
27
  if (hasEntry)
26
28
  return;
27
29
  }
28
- const prefix = content.endsWith('\n') || content.length === 0 ? '' : '\n';
30
+ const prefix = content.endsWith("\n") || content.length === 0 ? "" : "\n";
29
31
  appendFileSync(GITIGNORE_PATH, `${prefix}${entry}\n`);
30
32
  };
31
33
  const finalizeSuccess = (message) => {
@@ -36,11 +38,11 @@ export async function setupVoskModel(projectRoot, options) {
36
38
  return true;
37
39
  };
38
40
  const manualFallback = () => {
39
- log.plain('');
40
- log.info('Manual setup:');
41
- log.plain(' 1. Download: https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip');
42
- log.plain(' 2. Extract to: apps/native/assets/vosk-model/');
43
- log.plain(' 3. Rename folder to: model-en-us');
41
+ log.plain("");
42
+ log.info("Manual setup:");
43
+ log.plain(" 1. Download: https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip");
44
+ log.plain(" 2. Extract to: apps/native/assets/vosk-model/");
45
+ log.plain(" 3. Rename folder to: model-en-us");
44
46
  return false;
45
47
  };
46
48
  try {
@@ -48,16 +50,16 @@ export async function setupVoskModel(projectRoot, options) {
48
50
  if (existsSync(LEGACY_MODEL_PATH) && !existsSync(MODEL_PATH)) {
49
51
  mkdirSync(ASSETS_DIR, { recursive: true });
50
52
  renameSync(LEGACY_MODEL_PATH, MODEL_PATH);
51
- log.info('✓ Moved existing Vosk model from legacy path to apps/native/assets/vosk-model');
53
+ log.info("✓ Moved existing Vosk model from legacy path to apps/native/assets/vosk-model");
52
54
  return finalizeSuccess();
53
55
  }
54
56
  // Check if model already exists
55
57
  if (existsSync(MODEL_PATH)) {
56
- log.info('✓ Vosk model already exists');
58
+ log.info("✓ Vosk model already exists");
57
59
  return finalizeSuccess();
58
60
  }
59
61
  if (options?.dryRun) {
60
- log.info('[DRY RUN] Would download Vosk model (~40MB)');
62
+ log.info("[DRY RUN] Would download Vosk model (~40MB)");
61
63
  return true;
62
64
  }
63
65
  // Create assets directory if it doesn't exist
@@ -67,13 +69,13 @@ export async function setupVoskModel(projectRoot, options) {
67
69
  let installed = false;
68
70
  // Attempt direct download first
69
71
  try {
70
- log.info('📥 Downloading Vosk model (~40MB)...');
72
+ log.info("📥 Downloading Vosk model (~40MB)...");
71
73
  await downloadFile(MODEL_URL, ZIP_PATH);
72
- log.info('📦 Extracting model...');
74
+ log.info("📦 Extracting model...");
73
75
  await extractZipSafe(ZIP_PATH, ASSETS_DIR);
74
- const extractedFolder = readdirSync(ASSETS_DIR).find((f) => f.startsWith('vosk-model-small-en-us'));
76
+ const extractedFolder = readdirSync(ASSETS_DIR).find((f) => f.startsWith("vosk-model-small-en-us"));
75
77
  if (!extractedFolder) {
76
- throw new Error('Extracted folder not found. The zip structure may have changed.');
78
+ throw new Error("Extracted folder not found. The zip structure may have changed.");
77
79
  }
78
80
  const extractedPath = join(ASSETS_DIR, extractedFolder);
79
81
  renameSync(extractedPath, MODEL_PATH);
@@ -81,13 +83,20 @@ export async function setupVoskModel(projectRoot, options) {
81
83
  installed = true;
82
84
  }
83
85
  catch (error) {
84
- log.info('Direct download failed, retrying with bundled script...');
86
+ log.info("Direct download failed, retrying with bundled script...");
85
87
  }
86
88
  // Fallback: try bundled script if direct download failed
87
- const scriptPath = resolve(projectRoot, 'apps/native/scripts/download-vosk-model.mjs');
89
+ const scriptPath = resolve(projectRoot, "apps/native/scripts/download-vosk-model.mjs");
88
90
  if (!installed && existsSync(scriptPath)) {
89
91
  try {
90
- execSync(`node ${scriptPath}`, { stdio: 'inherit', cwd: projectRoot });
92
+ // Use spawnSync with args array for safety (no shell interpolation)
93
+ const result = spawnSync("node", [scriptPath], {
94
+ stdio: "inherit",
95
+ cwd: projectRoot,
96
+ });
97
+ if (result.error) {
98
+ throw result.error;
99
+ }
91
100
  installed = existsSync(MODEL_PATH);
92
101
  }
93
102
  catch (e) {
@@ -95,7 +104,7 @@ export async function setupVoskModel(projectRoot, options) {
95
104
  }
96
105
  }
97
106
  if (installed) {
98
- return finalizeSuccess('✓ Vosk model ready');
107
+ return finalizeSuccess("✓ Vosk model ready");
99
108
  }
100
109
  return manualFallback();
101
110
  }
@@ -118,22 +127,24 @@ function downloadFile(url, dest) {
118
127
  .then(resolve)
119
128
  .catch(reject);
120
129
  }
121
- const totalSize = parseInt(response.headers['content-length'] || '0', 10);
130
+ const totalSize = parseInt(response.headers["content-length"] || "0", 10);
122
131
  let downloaded = 0;
123
- response.on('data', (chunk) => {
132
+ response.on("data", (chunk) => {
124
133
  downloaded += chunk.length;
125
134
  const percent = ((downloaded / totalSize) * 100).toFixed(1);
126
- process.stdout.write(`\r ${percent}% (${(downloaded / 1024 / 1024).toFixed(1)}MB / ${(totalSize / 1024 / 1024).toFixed(1)}MB)`);
135
+ process.stdout.write(`\r ${percent}% (${(downloaded / 1024 / 1024).toFixed(1)}MB / ${(totalSize /
136
+ 1024 /
137
+ 1024).toFixed(1)}MB)`);
127
138
  });
128
139
  response.pipe(file);
129
- file.on('finish', () => {
140
+ file.on("finish", () => {
130
141
  file.close(() => {
131
- process.stdout.write('\r');
142
+ process.stdout.write("\r");
132
143
  resolve();
133
144
  });
134
145
  });
135
146
  })
136
- .on('error', (err) => {
147
+ .on("error", (err) => {
137
148
  unlinkSync(dest);
138
149
  reject(err);
139
150
  });
@@ -1 +1 @@
1
- {"version":3,"file":"vosk.js","sourceRoot":"","sources":["../../src/core/vosk.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vosk.js","sourceRoot":"","sources":["../../src/core/vosk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ # Manual Testing Guide
2
+
3
+ This guide explains how to manually test the `vibefast-cli` during development without affecting your globally installed version (if any).
4
+
5
+ ## Prerequisites
6
+
7
+ - You are in the `vibefast-cli` directory.
8
+ - You have run `npm install`.
9
+
10
+ ## Method 1: The "Alias" Method (Recommended)
11
+
12
+ This method allows you to run your local build as `vf-dev` without overwriting your global `vf` command.
13
+
14
+ 1. **Build the CLI**:
15
+
16
+ ```bash
17
+ npm run build
18
+ ```
19
+
20
+ 2. **Create an Alias** (run this in your terminal):
21
+
22
+ ```bash
23
+ # Run this inside the vibefast-cli directory
24
+ alias vf-dev="node $(pwd)/dist/index.js"
25
+ ```
26
+
27
+ 3. **Test in a Sandbox**:
28
+
29
+ ```bash
30
+ # Go to a temporary directory
31
+ mkdir ~/Desktop/vf-playground
32
+ cd ~/Desktop/vf-playground
33
+
34
+ # Run your local CLI
35
+ vf-dev init
36
+ vf-dev add chatbot
37
+ ```
38
+
39
+ ## Method 2: The "Link" Method
40
+
41
+ Use this if you want to replace your global `vf` command with your local version.
42
+
43
+ 1. **Build**:
44
+
45
+ ```bash
46
+ npm run build
47
+ ```
48
+
49
+ 2. **Link**:
50
+
51
+ ```bash
52
+ npm link
53
+ ```
54
+
55
+ 3. **Test**:
56
+ Now `vf` runs your local code anywhere.
57
+
58
+ 4. **Unlink (Revert)**:
59
+ ```bash
60
+ npm unlink -g vibefast-cli
61
+ # Then reinstall the production version if needed
62
+ npm i -g vibefast-cli
63
+ ```
64
+
65
+ ## What to Test?
66
+
67
+ ### 1. Initialization
68
+
69
+ - Run `vf init`.
70
+ - Check if `.vibefast/starter.json` is created.
71
+ - Check if it asks for a license key (if not already saved).
72
+
73
+ ### 2. Adding Features
74
+
75
+ - Run `vf add <feature>`.
76
+ - **Verify**:
77
+ - Files are copied to `apps/native` or `apps/web`.
78
+ - `app.config.ts` (Native) has the plugin added (if applicable).
79
+ - `package.json` dependencies are updated (or prompted).
80
+
81
+ ### 3. Removing Features
82
+
83
+ - Run `vf remove <feature>`.
84
+ - **Verify**:
85
+ - Files are deleted.
86
+ - `app.config.ts` plugin is removed (if implemented) or you are warned.
87
+
88
+ ### 4. Edge Cases
89
+
90
+ - Run in a folder that is _not_ a VibeFast project (should fail gracefully).
91
+ - Run with invalid arguments.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibefast-cli",
3
- "version": "1.1.3",
3
+ "version": "1.2.1",
4
4
  "description": "CLI for installing VibeFast features into your monorepo",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,7 +10,8 @@
10
10
  "build": "tsc",
11
11
  "dev": "tsx src/index.ts",
12
12
  "test": "vitest",
13
- "prepublishOnly": "npm run build"
13
+ "prepublishOnly": "npm run build",
14
+ "prepare": "husky"
14
15
  },
15
16
  "keywords": [
16
17
  "vibefast",
@@ -47,6 +48,7 @@
47
48
  "picocolors": "^1.0.0",
48
49
  "readline-sync": "^1.4.10",
49
50
  "simple-git": "^3.30.0",
51
+ "ts-morph": "^27.0.2",
50
52
  "yauzl": "^2.10.0"
51
53
  },
52
54
  "devDependencies": {
@@ -54,11 +56,12 @@
54
56
  "@types/node": "^20.11.0",
55
57
  "@types/readline-sync": "^1.4.8",
56
58
  "@types/yauzl": "^2.10.3",
59
+ "husky": "^9.1.7",
57
60
  "tsx": "^4.7.0",
58
61
  "typescript": "^5.3.3",
59
62
  "vitest": "^1.2.0"
60
63
  },
61
64
  "engines": {
62
- "node": ">=18.0.0"
65
+ "node": ">=20.10.0"
63
66
  }
64
67
  }
@@ -0,0 +1,5 @@
1
+ import { RecordingListDemo } from '@/features/audio-recorder/demo/with-recording-list-demo';
2
+
3
+ export default function AudioRecorderScreen() {
4
+ return <RecordingListDemo />;
5
+ }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "audio-recorder",
3
- "version": "1.0.1",
3
+ "version": "1.0.0",
4
4
  "description": "Record and manage voice notes",
5
5
  "copy": [
6
6
  {
7
- "from": "apps/native/src/app/(root)/(protected)/audio-recorder",
7
+ "from": "apps/native/src/app/audio-recorder",
8
8
  "to": "apps/native/src/app/(root)/(protected)/audio-recorder"
9
9
  },
10
10
  {
@@ -19,4 +19,4 @@
19
19
  "color": "#EF4444"
20
20
  },
21
21
  "target": "native"
22
- }
22
+ }
@@ -0,0 +1,301 @@
1
+ import {
2
+ type AudioSource,
3
+ useAudioPlayer,
4
+ useAudioPlayerStatus,
5
+ } from 'expo-audio';
6
+ import { useCallback, useEffect, useState } from 'react';
7
+ import { View, type ViewStyle } from 'react-native';
8
+ import { tv } from 'tailwind-variants';
9
+
10
+ import { Button, Icon, Text } from '@/components/ui';
11
+ import { useThemeConfig } from '@/lib/use-theme-config';
12
+
13
+ // import { Progress } from '@/components/ui/progress';
14
+ import { AudioWaveform } from './audio-waveform';
15
+
16
+ const audioPlayerStyles = tv({
17
+ slots: {
18
+ container: 'm-2 rounded-2xl p-4',
19
+ waveformContainer: 'mb-3 items-center',
20
+ progressBarContainer: 'mb-3 px-1',
21
+ timerContainer: 'mb-3 flex-row items-center justify-between',
22
+ timerText: 'font-mono text-sm text-muted',
23
+ controlsContainer: 'mt-2 flex-row items-center justify-center gap-4',
24
+ controlButton: 'size-14',
25
+ playPauseButton: 'size-16 rounded-full',
26
+ loadingContainer: 'items-center p-2',
27
+ loadingText: 'text-muted',
28
+ },
29
+ variants: {
30
+ shrinked: {
31
+ true: {
32
+ container: 'm-0 rounded-2xl p-2',
33
+ waveformContainer: 'mb-0 items-center',
34
+ progressBarContainer: 'mb-0 px-1',
35
+ timerContainer: 'mb-0 flex-row items-center justify-between',
36
+ controlsContainer: 'mt-0 flex-row items-center justify-center gap-2',
37
+ },
38
+ },
39
+ },
40
+ });
41
+
42
+ export interface AudioPlayerProps {
43
+ source: AudioSource;
44
+ shrinked?: boolean;
45
+ style?: ViewStyle & { className?: string };
46
+ showControls?: boolean;
47
+ showWaveform?: boolean;
48
+ showTimer?: boolean;
49
+ showProgressBar?: boolean;
50
+ autoPlay?: boolean;
51
+ onPlaybackStatusUpdate?: (status: any) => void;
52
+ // Custom sizing props for compact mode
53
+ waveformHeight?: number;
54
+ waveformBarCount?: number;
55
+ waveformBarWidth?: number;
56
+ waveformBarGap?: number;
57
+ controlButtonSize?: number;
58
+ playButtonSize?: number;
59
+ }
60
+
61
+ export function AudioPlayer({
62
+ source,
63
+ style,
64
+ shrinked = false,
65
+ showControls = true,
66
+ showWaveform = true,
67
+ showTimer = true,
68
+ // showProgressBar = true,
69
+ autoPlay = false,
70
+ onPlaybackStatusUpdate,
71
+ // Custom sizing with defaults
72
+ waveformHeight = 80,
73
+ waveformBarCount = 60,
74
+ waveformBarWidth = 4,
75
+ waveformBarGap = 1.5,
76
+ controlButtonSize = 24,
77
+ playButtonSize = 28,
78
+ }: AudioPlayerProps) {
79
+ const {
80
+ container,
81
+ waveformContainer,
82
+ // progressBarContainer,
83
+ timerContainer,
84
+ timerText,
85
+ controlsContainer,
86
+ controlButton,
87
+ playPauseButton,
88
+ loadingContainer,
89
+ loadingText,
90
+ } = audioPlayerStyles({ shrinked });
91
+ const theme = useThemeConfig();
92
+ const player = useAudioPlayer(source);
93
+ const status = useAudioPlayerStatus(player);
94
+ const [duration, setDuration] = useState(0);
95
+ const [position, setPosition] = useState(0);
96
+ const [isSeeking, setIsSeeking] = useState(false);
97
+
98
+ // Enhanced waveform data - more bars for smoother visualization
99
+ const [waveformData] = useState<number[]>(
100
+ Array.from({ length: 60 }, (_, i) => {
101
+ // Create more varied and realistic waveform pattern
102
+ const base1 = Math.sin((i / 60) * Math.PI * 6) * 0.4 + 0.5;
103
+ const base2 = Math.sin((i / 60) * Math.PI * 2.5) * 0.3 + 0.4;
104
+ const noise = (Math.random() - 0.5) * 0.25;
105
+ const peak = Math.random() < 0.15 ? Math.random() * 0.4 : 0; // Occasional peaks
106
+ return Math.max(0.15, Math.min(0.95, (base1 + base2) / 2 + noise + peak));
107
+ }),
108
+ );
109
+
110
+ useEffect(() => {
111
+ if (autoPlay && player.isLoaded && !player.playing) {
112
+ player.play();
113
+ }
114
+ }, [autoPlay, player]);
115
+
116
+ useEffect(() => {
117
+ if (!isSeeking && status?.isLoaded) {
118
+ setDuration(status.duration || 0);
119
+ setPosition(status.currentTime || 0);
120
+
121
+ if (status.didJustFinish && status.duration > 0) {
122
+ player.seekTo(0);
123
+ player.pause();
124
+ }
125
+
126
+ onPlaybackStatusUpdate?.(status);
127
+ }
128
+ }, [status, isSeeking, player, onPlaybackStatusUpdate]);
129
+
130
+ const handlePlayPause = () => {
131
+ if (player.playing) {
132
+ player.pause();
133
+ } else {
134
+ player.play();
135
+ }
136
+ };
137
+
138
+ const handleBackFiveSeconds = () => {
139
+ const newPosition = Math.max(0, position - 5);
140
+ seekToPosition(newPosition);
141
+ };
142
+
143
+ const handleRestart = () => {
144
+ seekToPosition(0);
145
+ };
146
+
147
+ // Unified seeking function
148
+ const seekToPosition = useCallback(
149
+ (newPosition: number) => {
150
+ if (player.isLoaded && duration > 0) {
151
+ const clampedPosition = Math.max(0, Math.min(duration, newPosition));
152
+ player.seekTo(clampedPosition);
153
+ setPosition(clampedPosition);
154
+ }
155
+ },
156
+ [player, duration],
157
+ );
158
+
159
+ // Handle waveform seeking
160
+ const handleWaveformSeek = useCallback(
161
+ (seekPercentage: number) => {
162
+ if (duration > 0) {
163
+ const newPosition = (seekPercentage / 100) * duration;
164
+ seekToPosition(newPosition);
165
+ }
166
+ },
167
+ [duration, seekToPosition],
168
+ );
169
+
170
+ // Handle progress bar seeking
171
+ // const handleProgressSeek = useCallback(
172
+ // (progressValue: number) => {
173
+ // if (duration > 0) {
174
+ // const newPosition = (progressValue / 100) * duration;
175
+ // seekToPosition(newPosition);
176
+ // }
177
+ // },
178
+ // [duration, seekToPosition]
179
+ // );
180
+
181
+ // Handle seeking start/end for smooth updates
182
+ const handleSeekStart = useCallback(() => {
183
+ setIsSeeking(true);
184
+ }, []);
185
+
186
+ const handleSeekEnd = useCallback(() => {
187
+ setIsSeeking(false);
188
+ }, []);
189
+
190
+ const formatTime = (seconds: number) => {
191
+ const mins = Math.floor(seconds / 60);
192
+ const secs = Math.floor(seconds % 60);
193
+ return `${mins}:${secs.toString().padStart(2, '0')}`;
194
+ };
195
+
196
+ const progressPercentage = duration > 0 ? (position / duration) * 100 : 0;
197
+
198
+ return (
199
+ <View className={container({ class: style?.className })}>
200
+ {/* Waveform Visualization with seeking capability */}
201
+ {showWaveform && (
202
+ <View className={waveformContainer()}>
203
+ <AudioWaveform
204
+ data={waveformData}
205
+ isPlaying={player.playing}
206
+ progress={progressPercentage}
207
+ onSeek={handleWaveformSeek}
208
+ onSeekStart={handleSeekStart}
209
+ onSeekEnd={handleSeekEnd}
210
+ height={waveformHeight}
211
+ barCount={waveformBarCount}
212
+ barWidth={waveformBarWidth}
213
+ barGap={waveformBarGap}
214
+ animated={true}
215
+ showProgress={true}
216
+ interactive={true} // Enable seeking
217
+ />
218
+ </View>
219
+ )}
220
+
221
+ {/* Interactive Progress Bar */}
222
+ {/* {showProgressBar && (
223
+ <View className={progressBarContainer()}>
224
+ <Progress
225
+ value={progressPercentage}
226
+ onValueChange={handleProgressSeek}
227
+ onSeekStart={handleSeekStart}
228
+ onSeekEnd={handleSeekEnd}
229
+ style={{ height: 8 }}
230
+ indicatorClassName="bg-destructive"
231
+ />
232
+ </View>
233
+ )} */}
234
+
235
+ {/* Timer Display */}
236
+ {showTimer && (
237
+ <View className={timerContainer()}>
238
+ <Text className={timerText()}>{formatTime(position)}</Text>
239
+ <Text className={timerText()}>{formatTime(duration)}</Text>
240
+ </View>
241
+ )}
242
+
243
+ {/* Playback Controls */}
244
+ {showControls && (
245
+ <View className={controlsContainer()}>
246
+ {/* Back 5s Button */}
247
+ <Button
248
+ variant="ghost"
249
+ size="icon"
250
+ className={controlButton()}
251
+ onPress={handleBackFiveSeconds}
252
+ disabled={!player.isLoaded}
253
+ >
254
+ <Icon name="refresh" size={controlButtonSize} />
255
+ </Button>
256
+
257
+ {/* Play/Pause Button */}
258
+ <Button
259
+ variant="default"
260
+ size="icon"
261
+ className={playPauseButton()}
262
+ onPress={handlePlayPause}
263
+ disabled={!player.isLoaded}
264
+ >
265
+ {player.playing ? (
266
+ <Icon
267
+ name="pause"
268
+ size={playButtonSize}
269
+ color={theme.colors.background}
270
+ />
271
+ ) : (
272
+ <Icon
273
+ name="play"
274
+ size={playButtonSize}
275
+ color={theme.colors.background}
276
+ />
277
+ )}
278
+ </Button>
279
+
280
+ {/* Stop Button */}
281
+ <Button
282
+ variant="ghost"
283
+ size="icon"
284
+ className={controlButton()}
285
+ onPress={handleRestart}
286
+ disabled={!player.isLoaded}
287
+ >
288
+ <Icon name="stop" size={controlButtonSize} />
289
+ </Button>
290
+ </View>
291
+ )}
292
+
293
+ {/* Loading State */}
294
+ {!player.isLoaded && (
295
+ <View className={loadingContainer()}>
296
+ <Text className={loadingText()}>Loading audio...</Text>
297
+ </View>
298
+ )}
299
+ </View>
300
+ );
301
+ }