@onairos/react-native 3.1.18 โ†’ 3.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 (734) hide show
  1. package/README.md +374 -403
  2. package/lib/commonjs/api/index.js +1 -75
  3. package/lib/commonjs/api/index.js.map +1 -1
  4. package/lib/commonjs/assets/images/email.png +0 -0
  5. package/lib/commonjs/assets/images/linkedin.png +0 -0
  6. package/lib/commonjs/assets/images/reddit.png +0 -0
  7. package/lib/commonjs/assets/images/youtube.png +0 -0
  8. package/lib/commonjs/components/DataRequestModal.js.map +1 -1
  9. package/lib/commonjs/components/DataRequestScreen.js.map +1 -1
  10. package/lib/commonjs/components/EmailVerificationModal.js.map +1 -1
  11. package/lib/commonjs/components/Onairos.js +3 -1
  12. package/lib/commonjs/components/Onairos.js.map +1 -1
  13. package/lib/commonjs/components/OnairosButton.js +190 -171
  14. package/lib/commonjs/components/OnairosButton.js.map +1 -1
  15. package/lib/commonjs/components/Overlay.js +5 -5
  16. package/lib/commonjs/components/Overlay.js.map +1 -1
  17. package/lib/commonjs/components/PinInput.js +120 -282
  18. package/lib/commonjs/components/PinInput.js.map +1 -1
  19. package/lib/commonjs/components/PlatformList.js.map +1 -1
  20. package/lib/commonjs/components/TrainingModal.js +563 -808
  21. package/lib/commonjs/components/TrainingModal.js.map +1 -1
  22. package/lib/commonjs/components/UniversalOnboarding.js +1296 -2302
  23. package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
  24. package/lib/commonjs/components/UniversalOnboarding.tsx.new +455 -0
  25. package/lib/commonjs/components/onboarding/OAuthWebView.js +743 -134
  26. package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
  27. package/lib/commonjs/components/onboarding/OnboardingHeader.js.map +1 -1
  28. package/lib/commonjs/components/onboarding/PinInput.js.map +1 -1
  29. package/lib/commonjs/components/onboarding/PlatformConnector.js.map +1 -1
  30. package/lib/commonjs/components/screens/ConnectorScreen.js.map +1 -1
  31. package/lib/commonjs/components/screens/LoadingScreen.js.map +1 -1
  32. package/lib/commonjs/components/screens/PinCreationScreen.js.map +1 -1
  33. package/lib/commonjs/constants/index.js.map +1 -1
  34. package/lib/commonjs/hooks/useConnections.js +125 -120
  35. package/lib/commonjs/hooks/useConnections.js.map +1 -1
  36. package/lib/commonjs/hooks/useCredentials.js.map +1 -1
  37. package/lib/commonjs/index.js +27 -157
  38. package/lib/commonjs/index.js.map +1 -1
  39. package/lib/commonjs/services/SDK_API_KEY_VALIDATION.md +428 -0
  40. package/lib/commonjs/services/apiKeyService.js +106 -105
  41. package/lib/commonjs/services/apiKeyService.js.map +1 -1
  42. package/lib/commonjs/services/oauthService.js.map +1 -1
  43. package/lib/commonjs/services/platformAuthService.js +722 -956
  44. package/lib/commonjs/services/platformAuthService.js.map +1 -1
  45. package/lib/commonjs/types/ambient.d.js.map +1 -1
  46. package/lib/commonjs/types/declarations.d.js.map +1 -1
  47. package/lib/commonjs/types/index.d.js.map +1 -1
  48. package/lib/commonjs/types/index.js.map +1 -1
  49. package/lib/commonjs/types/node-fix.d.js.map +1 -1
  50. package/lib/commonjs/types/node-override.d.js.map +1 -1
  51. package/lib/commonjs/types/opacity.d.js.map +1 -1
  52. package/lib/commonjs/types/types.d.js.map +1 -1
  53. package/lib/commonjs/types.js.map +1 -1
  54. package/lib/commonjs/utils/Portal.js +4 -4
  55. package/lib/commonjs/utils/Portal.js.map +1 -1
  56. package/lib/commonjs/utils/api.js +24 -24
  57. package/lib/commonjs/utils/api.js.map +1 -1
  58. package/lib/commonjs/utils/auth.js +18 -18
  59. package/lib/commonjs/utils/auth.js.map +1 -1
  60. package/lib/commonjs/utils/crypto.js +13 -13
  61. package/lib/commonjs/utils/crypto.js.map +1 -1
  62. package/lib/commonjs/utils/debugHelper.js.map +1 -1
  63. package/lib/commonjs/utils/encryption.js +12 -12
  64. package/lib/commonjs/utils/encryption.js.map +1 -1
  65. package/lib/commonjs/utils/onairosApi.js.map +1 -1
  66. package/lib/commonjs/utils/programmaticFlow.js +16 -16
  67. package/lib/commonjs/utils/programmaticFlow.js.map +1 -1
  68. package/lib/commonjs/utils/retryHelper.js +27 -27
  69. package/lib/commonjs/utils/retryHelper.js.map +1 -1
  70. package/lib/commonjs/utils/secureStorage.js.map +1 -1
  71. package/lib/module/api/index.js +0 -72
  72. package/lib/module/api/index.js.map +1 -1
  73. package/lib/module/assets/images/email.png +0 -0
  74. package/lib/module/assets/images/linkedin.png +0 -0
  75. package/lib/module/assets/images/reddit.png +0 -0
  76. package/lib/module/assets/images/youtube.png +0 -0
  77. package/lib/module/components/DataRequestModal.js.map +1 -1
  78. package/lib/module/components/DataRequestScreen.js.map +1 -1
  79. package/lib/module/components/EmailVerificationModal.js.map +1 -1
  80. package/lib/module/components/Onairos.js +3 -1
  81. package/lib/module/components/Onairos.js.map +1 -1
  82. package/lib/module/components/OnairosButton.js +192 -172
  83. package/lib/module/components/OnairosButton.js.map +1 -1
  84. package/lib/module/components/Overlay.js +5 -5
  85. package/lib/module/components/Overlay.js.map +1 -1
  86. package/lib/module/components/PinInput.js +120 -283
  87. package/lib/module/components/PinInput.js.map +1 -1
  88. package/lib/module/components/PlatformList.js.map +1 -1
  89. package/lib/module/components/TrainingModal.js +565 -809
  90. package/lib/module/components/TrainingModal.js.map +1 -1
  91. package/lib/module/components/UniversalOnboarding.js +1297 -2305
  92. package/lib/module/components/UniversalOnboarding.js.map +1 -1
  93. package/lib/module/components/UniversalOnboarding.tsx.new +455 -0
  94. package/lib/module/components/onboarding/OAuthWebView.js +744 -136
  95. package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
  96. package/lib/module/components/onboarding/OnboardingHeader.js.map +1 -1
  97. package/lib/module/components/onboarding/PinInput.js.map +1 -1
  98. package/lib/module/components/onboarding/PlatformConnector.js.map +1 -1
  99. package/lib/module/components/screens/ConnectorScreen.js.map +1 -1
  100. package/lib/module/components/screens/LoadingScreen.js.map +1 -1
  101. package/lib/module/components/screens/PinCreationScreen.js.map +1 -1
  102. package/lib/module/constants/index.js.map +1 -1
  103. package/lib/module/hooks/useConnections.js +125 -119
  104. package/lib/module/hooks/useConnections.js.map +1 -1
  105. package/lib/module/hooks/useCredentials.js.map +1 -1
  106. package/lib/module/index.js +17 -55
  107. package/lib/module/index.js.map +1 -1
  108. package/lib/module/services/SDK_API_KEY_VALIDATION.md +428 -0
  109. package/lib/module/services/apiKeyService.js +106 -105
  110. package/lib/module/services/apiKeyService.js.map +1 -1
  111. package/lib/module/services/oauthService.js.map +1 -1
  112. package/lib/module/services/platformAuthService.js +704 -943
  113. package/lib/module/services/platformAuthService.js.map +1 -1
  114. package/lib/module/types/ambient.d.js.map +1 -1
  115. package/lib/module/types/declarations.d.js.map +1 -1
  116. package/lib/module/types/index.d.js.map +1 -1
  117. package/lib/module/types/index.js.map +1 -1
  118. package/lib/module/types/node-fix.d.js.map +1 -1
  119. package/lib/module/types/node-override.d.js.map +1 -1
  120. package/lib/module/types/opacity.d.js.map +1 -1
  121. package/lib/module/types/types.d.js.map +1 -1
  122. package/lib/module/types.js.map +1 -1
  123. package/lib/module/utils/Portal.js +4 -4
  124. package/lib/module/utils/Portal.js.map +1 -1
  125. package/lib/module/utils/api.js +24 -24
  126. package/lib/module/utils/api.js.map +1 -1
  127. package/lib/module/utils/auth.js +18 -18
  128. package/lib/module/utils/auth.js.map +1 -1
  129. package/lib/module/utils/crypto.js +13 -13
  130. package/lib/module/utils/crypto.js.map +1 -1
  131. package/lib/module/utils/debugHelper.js.map +1 -1
  132. package/lib/module/utils/encryption.js +12 -12
  133. package/lib/module/utils/encryption.js.map +1 -1
  134. package/lib/module/utils/onairosApi.js.map +1 -1
  135. package/lib/module/utils/programmaticFlow.js +16 -16
  136. package/lib/module/utils/programmaticFlow.js.map +1 -1
  137. package/lib/module/utils/retryHelper.js +27 -27
  138. package/lib/module/utils/retryHelper.js.map +1 -1
  139. package/lib/module/utils/secureStorage.js.map +1 -1
  140. package/lib/typescript/api/index.d.ts +7 -15
  141. package/lib/typescript/api/index.d.ts.map +1 -1
  142. package/lib/typescript/components/DataRequestModal.d.ts +10 -10
  143. package/lib/typescript/components/DataRequestScreen.d.ts +10 -10
  144. package/lib/typescript/components/EmailVerificationModal.d.ts +10 -10
  145. package/lib/typescript/components/Onairos.d.ts +3 -3
  146. package/lib/typescript/components/Onairos.d.ts.map +1 -1
  147. package/lib/typescript/components/OnairosButton.d.ts +11 -36
  148. package/lib/typescript/components/OnairosButton.d.ts.map +1 -1
  149. package/lib/typescript/components/Overlay.d.ts +3 -3
  150. package/lib/typescript/components/PinInput.d.ts +3 -13
  151. package/lib/typescript/components/PinInput.d.ts.map +1 -1
  152. package/lib/typescript/components/PlatformList.d.ts +3 -3
  153. package/lib/typescript/components/TrainingModal.d.ts +3 -14
  154. package/lib/typescript/components/TrainingModal.d.ts.map +1 -1
  155. package/lib/typescript/components/UniversalOnboarding.d.ts +3 -16
  156. package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
  157. package/lib/typescript/components/onboarding/OAuthWebView.d.ts +9 -9
  158. package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -1
  159. package/lib/typescript/components/onboarding/OnboardingHeader.d.ts +10 -10
  160. package/lib/typescript/components/onboarding/PinInput.d.ts +3 -3
  161. package/lib/typescript/components/onboarding/PlatformConnector.d.ts +12 -12
  162. package/lib/typescript/components/screens/ConnectorScreen.d.ts +8 -8
  163. package/lib/typescript/components/screens/LoadingScreen.d.ts +8 -8
  164. package/lib/typescript/components/screens/PinCreationScreen.d.ts +9 -9
  165. package/lib/typescript/constants/index.d.ts +52 -52
  166. package/lib/typescript/hooks/useConnections.d.ts +8 -13
  167. package/lib/typescript/hooks/useConnections.d.ts.map +1 -1
  168. package/lib/typescript/hooks/useCredentials.d.ts +8 -8
  169. package/lib/typescript/index.d.ts +17 -38
  170. package/lib/typescript/index.d.ts.map +1 -1
  171. package/lib/typescript/services/apiKeyService.d.ts +131 -131
  172. package/lib/typescript/services/apiKeyService.d.ts.map +1 -1
  173. package/lib/typescript/services/oauthService.d.ts +49 -49
  174. package/lib/typescript/services/platformAuthService.d.ts +143 -68
  175. package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
  176. package/lib/typescript/types/index.d.ts +228 -264
  177. package/lib/typescript/types/index.d.ts.map +1 -1
  178. package/lib/typescript/types.d.ts +268 -266
  179. package/lib/typescript/types.d.ts.map +1 -1
  180. package/lib/typescript/utils/Portal.d.ts +13 -13
  181. package/lib/typescript/utils/api.d.ts +5 -5
  182. package/lib/typescript/utils/auth.d.ts +5 -5
  183. package/lib/typescript/utils/crypto.d.ts +3 -3
  184. package/lib/typescript/utils/debugHelper.d.ts +28 -28
  185. package/lib/typescript/utils/encryption.d.ts +18 -18
  186. package/lib/typescript/utils/onairosApi.d.ts +86 -86
  187. package/lib/typescript/utils/programmaticFlow.d.ts +22 -22
  188. package/lib/typescript/utils/retryHelper.d.ts +68 -68
  189. package/lib/typescript/utils/secureStorage.d.ts +93 -93
  190. package/package.json +149 -145
  191. package/src/api/index.ts +110 -151
  192. package/src/assets/images/email.png +0 -0
  193. package/src/assets/images/linkedin.png +0 -0
  194. package/src/assets/images/reddit.png +0 -0
  195. package/src/assets/images/youtube.png +0 -0
  196. package/src/components/DataRequestScreen.tsx +355 -355
  197. package/src/components/EmailVerificationModal.tsx +363 -363
  198. package/src/components/Onairos.tsx +424 -422
  199. package/src/components/OnairosButton.tsx +359 -339
  200. package/src/components/Overlay.tsx +506 -506
  201. package/src/components/PinInput.tsx +343 -555
  202. package/src/components/PlatformList.tsx +144 -144
  203. package/src/components/TrainingModal.tsx +737 -1047
  204. package/src/components/UniversalOnboarding.tsx +1839 -2888
  205. package/src/components/UniversalOnboarding.tsx.new +455 -0
  206. package/src/components/onboarding/OAuthWebView.tsx +838 -232
  207. package/src/hooks/useConnections.ts +163 -161
  208. package/src/hooks/useCredentials.ts +174 -174
  209. package/src/index.js +14 -14
  210. package/src/index.ts +49 -99
  211. package/src/services/SDK_API_KEY_VALIDATION.md +428 -0
  212. package/src/services/apiKeyService.ts +921 -919
  213. package/src/services/platformAuthService.ts +1113 -1346
  214. package/src/types/ambient.d.ts +28 -28
  215. package/src/types/index.ts +241 -265
  216. package/src/types/node-fix.d.ts +18 -18
  217. package/src/types/node-override.d.ts +23 -23
  218. package/src/types/opacity.d.ts +15 -15
  219. package/src/types/types.d.ts +17 -17
  220. package/src/types.ts +6 -4
  221. package/src/utils/Portal.tsx +82 -82
  222. package/src/utils/api.js +111 -111
  223. package/src/utils/auth.js +103 -103
  224. package/src/utils/crypto.js +59 -59
  225. package/src/utils/encryption.ts +68 -68
  226. package/src/utils/programmaticFlow.ts +112 -112
  227. package/src/utils/retryHelper.ts +274 -274
  228. package/types/index.d.ts +213 -213
  229. package/types/node-env.d.ts +14 -14
  230. package/lib/commonjs/assets/fonts/EBGaramond-VariableFont_wght.ttf +0 -0
  231. package/lib/commonjs/assets/fonts/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
  232. package/lib/commonjs/assets/icons/Facebookicon.png +0 -0
  233. package/lib/commonjs/assets/icons/Gmail.png +0 -0
  234. package/lib/commonjs/assets/icons/Linkedinicon.png +0 -0
  235. package/lib/commonjs/assets/icons/Redditicon.png +0 -0
  236. package/lib/commonjs/assets/icons/YouTubeicon2.png +0 -0
  237. package/lib/commonjs/assets/icons/YouTubeicon3.png +0 -0
  238. package/lib/commonjs/assets/icons/farcaster.png +0 -0
  239. package/lib/commonjs/assets/icons/instagram.png +0 -0
  240. package/lib/commonjs/assets/icons/pinterest.png +0 -0
  241. package/lib/commonjs/assets/icons/swerv_logo.png +0 -0
  242. package/lib/commonjs/assets/icons/twitter.jpg +0 -0
  243. package/lib/commonjs/assets/images/Checkbox.svg +0 -3
  244. package/lib/commonjs/assets/images/EnochE.svg +0 -19
  245. package/lib/commonjs/assets/images/Enochicon1.png +0 -0
  246. package/lib/commonjs/assets/images/Face_ID_logo.png +0 -0
  247. package/lib/commonjs/assets/images/Facebookicon.png +0 -0
  248. package/lib/commonjs/assets/images/Gmail.png +0 -0
  249. package/lib/commonjs/assets/images/Googlelogo.png +0 -0
  250. package/lib/commonjs/assets/images/Linkedinicon.png +0 -0
  251. package/lib/commonjs/assets/images/Onairoslogo.png +0 -0
  252. package/lib/commonjs/assets/images/Personalityprofile.svg +0 -3
  253. package/lib/commonjs/assets/images/Personalitytraits.svg +0 -3
  254. package/lib/commonjs/assets/images/Redditicon.png +0 -0
  255. package/lib/commonjs/assets/images/Userpreferences.svg +0 -3
  256. package/lib/commonjs/assets/images/YouTubeicon3.png +0 -0
  257. package/lib/commonjs/assets/images/arrow.svg +0 -20
  258. package/lib/commonjs/assets/images/basicproficon.svg +0 -43
  259. package/lib/commonjs/assets/images/basicprofile.svg +0 -3
  260. package/lib/commonjs/assets/images/checkmark.svg +0 -4
  261. package/lib/commonjs/assets/images/contentanalysis.svg +0 -3
  262. package/lib/commonjs/assets/images/contenticon.svg +0 -23
  263. package/lib/commonjs/assets/images/persona1.png +0 -0
  264. package/lib/commonjs/assets/images/persona2.png +0 -0
  265. package/lib/commonjs/assets/images/persona3.png +0 -0
  266. package/lib/commonjs/assets/images/persona4.png +0 -0
  267. package/lib/commonjs/assets/images/persona5.png +0 -0
  268. package/lib/commonjs/assets/images/personalityicon.svg +0 -18
  269. package/lib/commonjs/assets/images/x-close.svg +0 -3
  270. package/lib/commonjs/components/BodyText.js +0 -27
  271. package/lib/commonjs/components/BodyText.js.map +0 -1
  272. package/lib/commonjs/components/BrandMark.js +0 -44
  273. package/lib/commonjs/components/BrandMark.js.map +0 -1
  274. package/lib/commonjs/components/CodeInput.js +0 -30
  275. package/lib/commonjs/components/CodeInput.js.map +0 -1
  276. package/lib/commonjs/components/EmailInput.js +0 -30
  277. package/lib/commonjs/components/EmailInput.js.map +0 -1
  278. package/lib/commonjs/components/ExistingUserDataConfirmation.js +0 -474
  279. package/lib/commonjs/components/ExistingUserDataConfirmation.js.map +0 -1
  280. package/lib/commonjs/components/GoogleButton.js +0 -55
  281. package/lib/commonjs/components/GoogleButton.js.map +0 -1
  282. package/lib/commonjs/components/HeadingGroup.js +0 -43
  283. package/lib/commonjs/components/HeadingGroup.js.map +0 -1
  284. package/lib/commonjs/components/ModalHeader.js +0 -99
  285. package/lib/commonjs/components/ModalHeader.js.map +0 -1
  286. package/lib/commonjs/components/ModalSheet.js +0 -47
  287. package/lib/commonjs/components/ModalSheet.js.map +0 -1
  288. package/lib/commonjs/components/OnairosSignInButton.js +0 -129
  289. package/lib/commonjs/components/OnairosSignInButton.js.map +0 -1
  290. package/lib/commonjs/components/PersonaImage.js +0 -60
  291. package/lib/commonjs/components/PersonaImage.js.map +0 -1
  292. package/lib/commonjs/components/PersonaLoadingScreen.js +0 -156
  293. package/lib/commonjs/components/PersonaLoadingScreen.js.map +0 -1
  294. package/lib/commonjs/components/PersonalizationConsentScreen.js +0 -316
  295. package/lib/commonjs/components/PersonalizationConsentScreen.js.map +0 -1
  296. package/lib/commonjs/components/PinCreationScreen.js +0 -393
  297. package/lib/commonjs/components/PinCreationScreen.js.map +0 -1
  298. package/lib/commonjs/components/PlatformConnectorsStep.js +0 -828
  299. package/lib/commonjs/components/PlatformConnectorsStep.js.map +0 -1
  300. package/lib/commonjs/components/PlatformToggle.js +0 -180
  301. package/lib/commonjs/components/PlatformToggle.js.map +0 -1
  302. package/lib/commonjs/components/PrimaryButton.js +0 -180
  303. package/lib/commonjs/components/PrimaryButton.js.map +0 -1
  304. package/lib/commonjs/components/SignInMatchAnimation.js +0 -197
  305. package/lib/commonjs/components/SignInMatchAnimation.js.map +0 -1
  306. package/lib/commonjs/components/SignInStep.js +0 -179
  307. package/lib/commonjs/components/SignInStep.js.map +0 -1
  308. package/lib/commonjs/components/VerificationStep.js +0 -154
  309. package/lib/commonjs/components/VerificationStep.js.map +0 -1
  310. package/lib/commonjs/components/WelcomeScreen.js +0 -401
  311. package/lib/commonjs/components/WelcomeScreen.js.map +0 -1
  312. package/lib/commonjs/components/icons/Basicproficon.js +0 -37
  313. package/lib/commonjs/components/icons/Basicproficon.js.map +0 -1
  314. package/lib/commonjs/components/icons/Basicprofile.js +0 -21
  315. package/lib/commonjs/components/icons/Basicprofile.js.map +0 -1
  316. package/lib/commonjs/components/icons/Checkbox.js +0 -21
  317. package/lib/commonjs/components/icons/Checkbox.js.map +0 -1
  318. package/lib/commonjs/components/icons/Checkmark.js +0 -27
  319. package/lib/commonjs/components/icons/Checkmark.js.map +0 -1
  320. package/lib/commonjs/components/icons/Contentanalysis.js +0 -21
  321. package/lib/commonjs/components/icons/Contentanalysis.js.map +0 -1
  322. package/lib/commonjs/components/icons/Contenticon.js +0 -39
  323. package/lib/commonjs/components/icons/Contenticon.js.map +0 -1
  324. package/lib/commonjs/components/icons/EnochE.js +0 -41
  325. package/lib/commonjs/components/icons/EnochE.js.map +0 -1
  326. package/lib/commonjs/components/icons/Personalityicon.js +0 -30
  327. package/lib/commonjs/components/icons/Personalityicon.js.map +0 -1
  328. package/lib/commonjs/components/icons/Personalityprofile.js +0 -21
  329. package/lib/commonjs/components/icons/Personalityprofile.js.map +0 -1
  330. package/lib/commonjs/components/icons/Personalitytraits.js +0 -21
  331. package/lib/commonjs/components/icons/Personalitytraits.js.map +0 -1
  332. package/lib/commonjs/components/icons/Userpreferences.js +0 -21
  333. package/lib/commonjs/components/icons/Userpreferences.js.map +0 -1
  334. package/lib/commonjs/components/icons/index.js +0 -84
  335. package/lib/commonjs/components/icons/index.js.map +0 -1
  336. package/lib/commonjs/config/api.js +0 -34
  337. package/lib/commonjs/config/api.js.map +0 -1
  338. package/lib/commonjs/context/AuthContext.js +0 -345
  339. package/lib/commonjs/context/AuthContext.js.map +0 -1
  340. package/lib/commonjs/hooks/useConnectedAccounts.js +0 -111
  341. package/lib/commonjs/hooks/useConnectedAccounts.js.map +0 -1
  342. package/lib/commonjs/hooks/useUserConnections.js +0 -148
  343. package/lib/commonjs/hooks/useUserConnections.js.map +0 -1
  344. package/lib/commonjs/services/apiClient.js +0 -302
  345. package/lib/commonjs/services/apiClient.js.map +0 -1
  346. package/lib/commonjs/services/authService.js +0 -935
  347. package/lib/commonjs/services/authService.js.map +0 -1
  348. package/lib/commonjs/services/biometricPinService.js +0 -184
  349. package/lib/commonjs/services/biometricPinService.js.map +0 -1
  350. package/lib/commonjs/services/connectedAccountsService.js +0 -268
  351. package/lib/commonjs/services/connectedAccountsService.js.map +0 -1
  352. package/lib/commonjs/services/googleAuthService.js +0 -268
  353. package/lib/commonjs/services/googleAuthService.js.map +0 -1
  354. package/lib/commonjs/services/imageCompressionService.js +0 -260
  355. package/lib/commonjs/services/imageCompressionService.js.map +0 -1
  356. package/lib/commonjs/services/jwtStorageService.js +0 -256
  357. package/lib/commonjs/services/jwtStorageService.js.map +0 -1
  358. package/lib/commonjs/services/mobileTrainingService.js +0 -185
  359. package/lib/commonjs/services/mobileTrainingService.js.map +0 -1
  360. package/lib/commonjs/services/pinEncryptionService.js +0 -84
  361. package/lib/commonjs/services/pinEncryptionService.js.map +0 -1
  362. package/lib/commonjs/services/pinStorageUtils.js +0 -105
  363. package/lib/commonjs/services/pinStorageUtils.js.map +0 -1
  364. package/lib/commonjs/services/storageService.js +0 -404
  365. package/lib/commonjs/services/storageService.js.map +0 -1
  366. package/lib/commonjs/services/trainingApiHelpers.js +0 -73
  367. package/lib/commonjs/services/trainingApiHelpers.js.map +0 -1
  368. package/lib/commonjs/services/userConnectionsService.js +0 -486
  369. package/lib/commonjs/services/userConnectionsService.js.map +0 -1
  370. package/lib/commonjs/services/youtubeMigrationService.js +0 -415
  371. package/lib/commonjs/services/youtubeMigrationService.js.map +0 -1
  372. package/lib/commonjs/theme/index.js +0 -249
  373. package/lib/commonjs/theme/index.js.map +0 -1
  374. package/lib/commonjs/utils/eventUtils.js +0 -288
  375. package/lib/commonjs/utils/eventUtils.js.map +0 -1
  376. package/lib/commonjs/utils/haptics.js +0 -66
  377. package/lib/commonjs/utils/haptics.js.map +0 -1
  378. package/lib/commonjs/utils/imagePreloader.js +0 -6
  379. package/lib/commonjs/utils/imagePreloader.js.map +0 -1
  380. package/lib/module/assets/fonts/EBGaramond-VariableFont_wght.ttf +0 -0
  381. package/lib/module/assets/fonts/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
  382. package/lib/module/assets/icons/Facebookicon.png +0 -0
  383. package/lib/module/assets/icons/Gmail.png +0 -0
  384. package/lib/module/assets/icons/Linkedinicon.png +0 -0
  385. package/lib/module/assets/icons/Redditicon.png +0 -0
  386. package/lib/module/assets/icons/YouTubeicon2.png +0 -0
  387. package/lib/module/assets/icons/YouTubeicon3.png +0 -0
  388. package/lib/module/assets/icons/farcaster.png +0 -0
  389. package/lib/module/assets/icons/instagram.png +0 -0
  390. package/lib/module/assets/icons/pinterest.png +0 -0
  391. package/lib/module/assets/icons/swerv_logo.png +0 -0
  392. package/lib/module/assets/icons/twitter.jpg +0 -0
  393. package/lib/module/assets/images/Checkbox.svg +0 -3
  394. package/lib/module/assets/images/EnochE.svg +0 -19
  395. package/lib/module/assets/images/Enochicon1.png +0 -0
  396. package/lib/module/assets/images/Face_ID_logo.png +0 -0
  397. package/lib/module/assets/images/Facebookicon.png +0 -0
  398. package/lib/module/assets/images/Gmail.png +0 -0
  399. package/lib/module/assets/images/Googlelogo.png +0 -0
  400. package/lib/module/assets/images/Linkedinicon.png +0 -0
  401. package/lib/module/assets/images/Onairoslogo.png +0 -0
  402. package/lib/module/assets/images/Personalityprofile.svg +0 -3
  403. package/lib/module/assets/images/Personalitytraits.svg +0 -3
  404. package/lib/module/assets/images/Redditicon.png +0 -0
  405. package/lib/module/assets/images/Userpreferences.svg +0 -3
  406. package/lib/module/assets/images/YouTubeicon3.png +0 -0
  407. package/lib/module/assets/images/arrow.svg +0 -20
  408. package/lib/module/assets/images/basicproficon.svg +0 -43
  409. package/lib/module/assets/images/basicprofile.svg +0 -3
  410. package/lib/module/assets/images/checkmark.svg +0 -4
  411. package/lib/module/assets/images/contentanalysis.svg +0 -3
  412. package/lib/module/assets/images/contenticon.svg +0 -23
  413. package/lib/module/assets/images/persona1.png +0 -0
  414. package/lib/module/assets/images/persona2.png +0 -0
  415. package/lib/module/assets/images/persona3.png +0 -0
  416. package/lib/module/assets/images/persona4.png +0 -0
  417. package/lib/module/assets/images/persona5.png +0 -0
  418. package/lib/module/assets/images/personalityicon.svg +0 -18
  419. package/lib/module/assets/images/x-close.svg +0 -3
  420. package/lib/module/components/BodyText.js +0 -20
  421. package/lib/module/components/BodyText.js.map +0 -1
  422. package/lib/module/components/BrandMark.js +0 -37
  423. package/lib/module/components/BrandMark.js.map +0 -1
  424. package/lib/module/components/CodeInput.js +0 -23
  425. package/lib/module/components/CodeInput.js.map +0 -1
  426. package/lib/module/components/EmailInput.js +0 -23
  427. package/lib/module/components/EmailInput.js.map +0 -1
  428. package/lib/module/components/ExistingUserDataConfirmation.js +0 -465
  429. package/lib/module/components/ExistingUserDataConfirmation.js.map +0 -1
  430. package/lib/module/components/GoogleButton.js +0 -48
  431. package/lib/module/components/GoogleButton.js.map +0 -1
  432. package/lib/module/components/HeadingGroup.js +0 -36
  433. package/lib/module/components/HeadingGroup.js.map +0 -1
  434. package/lib/module/components/ModalHeader.js +0 -92
  435. package/lib/module/components/ModalHeader.js.map +0 -1
  436. package/lib/module/components/ModalSheet.js +0 -39
  437. package/lib/module/components/ModalSheet.js.map +0 -1
  438. package/lib/module/components/OnairosSignInButton.js +0 -120
  439. package/lib/module/components/OnairosSignInButton.js.map +0 -1
  440. package/lib/module/components/PersonaImage.js +0 -53
  441. package/lib/module/components/PersonaImage.js.map +0 -1
  442. package/lib/module/components/PersonaLoadingScreen.js +0 -148
  443. package/lib/module/components/PersonaLoadingScreen.js.map +0 -1
  444. package/lib/module/components/PersonalizationConsentScreen.js +0 -309
  445. package/lib/module/components/PersonalizationConsentScreen.js.map +0 -1
  446. package/lib/module/components/PinCreationScreen.js +0 -386
  447. package/lib/module/components/PinCreationScreen.js.map +0 -1
  448. package/lib/module/components/PlatformConnectorsStep.js +0 -820
  449. package/lib/module/components/PlatformConnectorsStep.js.map +0 -1
  450. package/lib/module/components/PlatformToggle.js +0 -173
  451. package/lib/module/components/PlatformToggle.js.map +0 -1
  452. package/lib/module/components/PrimaryButton.js +0 -172
  453. package/lib/module/components/PrimaryButton.js.map +0 -1
  454. package/lib/module/components/SignInMatchAnimation.js +0 -189
  455. package/lib/module/components/SignInMatchAnimation.js.map +0 -1
  456. package/lib/module/components/SignInStep.js +0 -171
  457. package/lib/module/components/SignInStep.js.map +0 -1
  458. package/lib/module/components/VerificationStep.js +0 -146
  459. package/lib/module/components/VerificationStep.js.map +0 -1
  460. package/lib/module/components/WelcomeScreen.js +0 -393
  461. package/lib/module/components/WelcomeScreen.js.map +0 -1
  462. package/lib/module/components/icons/Basicproficon.js +0 -30
  463. package/lib/module/components/icons/Basicproficon.js.map +0 -1
  464. package/lib/module/components/icons/Basicprofile.js +0 -14
  465. package/lib/module/components/icons/Basicprofile.js.map +0 -1
  466. package/lib/module/components/icons/Checkbox.js +0 -14
  467. package/lib/module/components/icons/Checkbox.js.map +0 -1
  468. package/lib/module/components/icons/Checkmark.js +0 -20
  469. package/lib/module/components/icons/Checkmark.js.map +0 -1
  470. package/lib/module/components/icons/Contentanalysis.js +0 -14
  471. package/lib/module/components/icons/Contentanalysis.js.map +0 -1
  472. package/lib/module/components/icons/Contenticon.js +0 -32
  473. package/lib/module/components/icons/Contenticon.js.map +0 -1
  474. package/lib/module/components/icons/EnochE.js +0 -34
  475. package/lib/module/components/icons/EnochE.js.map +0 -1
  476. package/lib/module/components/icons/Personalityicon.js +0 -23
  477. package/lib/module/components/icons/Personalityicon.js.map +0 -1
  478. package/lib/module/components/icons/Personalityprofile.js +0 -14
  479. package/lib/module/components/icons/Personalityprofile.js.map +0 -1
  480. package/lib/module/components/icons/Personalitytraits.js +0 -14
  481. package/lib/module/components/icons/Personalitytraits.js.map +0 -1
  482. package/lib/module/components/icons/Userpreferences.js +0 -14
  483. package/lib/module/components/icons/Userpreferences.js.map +0 -1
  484. package/lib/module/components/icons/index.js +0 -13
  485. package/lib/module/components/icons/index.js.map +0 -1
  486. package/lib/module/config/api.js +0 -26
  487. package/lib/module/config/api.js.map +0 -1
  488. package/lib/module/context/AuthContext.js +0 -335
  489. package/lib/module/context/AuthContext.js.map +0 -1
  490. package/lib/module/hooks/useConnectedAccounts.js +0 -106
  491. package/lib/module/hooks/useConnectedAccounts.js.map +0 -1
  492. package/lib/module/hooks/useUserConnections.js +0 -140
  493. package/lib/module/hooks/useUserConnections.js.map +0 -1
  494. package/lib/module/services/apiClient.js +0 -298
  495. package/lib/module/services/apiClient.js.map +0 -1
  496. package/lib/module/services/authService.js +0 -905
  497. package/lib/module/services/authService.js.map +0 -1
  498. package/lib/module/services/biometricPinService.js +0 -173
  499. package/lib/module/services/biometricPinService.js.map +0 -1
  500. package/lib/module/services/connectedAccountsService.js +0 -255
  501. package/lib/module/services/connectedAccountsService.js.map +0 -1
  502. package/lib/module/services/googleAuthService.js +0 -258
  503. package/lib/module/services/googleAuthService.js.map +0 -1
  504. package/lib/module/services/imageCompressionService.js +0 -250
  505. package/lib/module/services/imageCompressionService.js.map +0 -1
  506. package/lib/module/services/jwtStorageService.js +0 -239
  507. package/lib/module/services/jwtStorageService.js.map +0 -1
  508. package/lib/module/services/mobileTrainingService.js +0 -172
  509. package/lib/module/services/mobileTrainingService.js.map +0 -1
  510. package/lib/module/services/pinEncryptionService.js +0 -75
  511. package/lib/module/services/pinEncryptionService.js.map +0 -1
  512. package/lib/module/services/pinStorageUtils.js +0 -93
  513. package/lib/module/services/pinStorageUtils.js.map +0 -1
  514. package/lib/module/services/storageService.js +0 -383
  515. package/lib/module/services/storageService.js.map +0 -1
  516. package/lib/module/services/trainingApiHelpers.js +0 -67
  517. package/lib/module/services/trainingApiHelpers.js.map +0 -1
  518. package/lib/module/services/userConnectionsService.js +0 -476
  519. package/lib/module/services/userConnectionsService.js.map +0 -1
  520. package/lib/module/services/youtubeMigrationService.js +0 -404
  521. package/lib/module/services/youtubeMigrationService.js.map +0 -1
  522. package/lib/module/theme/index.js +0 -244
  523. package/lib/module/theme/index.js.map +0 -1
  524. package/lib/module/utils/eventUtils.js +0 -270
  525. package/lib/module/utils/eventUtils.js.map +0 -1
  526. package/lib/module/utils/haptics.js +0 -59
  527. package/lib/module/utils/haptics.js.map +0 -1
  528. package/lib/module/utils/imagePreloader.js +0 -3
  529. package/lib/module/utils/imagePreloader.js.map +0 -1
  530. package/lib/typescript/components/BodyText.d.ts +0 -10
  531. package/lib/typescript/components/BodyText.d.ts.map +0 -1
  532. package/lib/typescript/components/BrandMark.d.ts +0 -11
  533. package/lib/typescript/components/BrandMark.d.ts.map +0 -1
  534. package/lib/typescript/components/CodeInput.d.ts +0 -10
  535. package/lib/typescript/components/CodeInput.d.ts.map +0 -1
  536. package/lib/typescript/components/EmailInput.d.ts +0 -8
  537. package/lib/typescript/components/EmailInput.d.ts.map +0 -1
  538. package/lib/typescript/components/ExistingUserDataConfirmation.d.ts +0 -12
  539. package/lib/typescript/components/ExistingUserDataConfirmation.d.ts.map +0 -1
  540. package/lib/typescript/components/GoogleButton.d.ts +0 -11
  541. package/lib/typescript/components/GoogleButton.d.ts.map +0 -1
  542. package/lib/typescript/components/HeadingGroup.d.ts +0 -11
  543. package/lib/typescript/components/HeadingGroup.d.ts.map +0 -1
  544. package/lib/typescript/components/ModalHeader.d.ts +0 -11
  545. package/lib/typescript/components/ModalHeader.d.ts.map +0 -1
  546. package/lib/typescript/components/ModalSheet.d.ts +0 -13
  547. package/lib/typescript/components/ModalSheet.d.ts.map +0 -1
  548. package/lib/typescript/components/OnairosSignInButton.d.ts +0 -13
  549. package/lib/typescript/components/OnairosSignInButton.d.ts.map +0 -1
  550. package/lib/typescript/components/PersonaImage.d.ts +0 -8
  551. package/lib/typescript/components/PersonaImage.d.ts.map +0 -1
  552. package/lib/typescript/components/PersonaLoadingScreen.d.ts +0 -10
  553. package/lib/typescript/components/PersonaLoadingScreen.d.ts.map +0 -1
  554. package/lib/typescript/components/PersonalizationConsentScreen.d.ts +0 -10
  555. package/lib/typescript/components/PersonalizationConsentScreen.d.ts.map +0 -1
  556. package/lib/typescript/components/PinCreationScreen.d.ts +0 -10
  557. package/lib/typescript/components/PinCreationScreen.d.ts.map +0 -1
  558. package/lib/typescript/components/PlatformConnectorsStep.d.ts +0 -11
  559. package/lib/typescript/components/PlatformConnectorsStep.d.ts.map +0 -1
  560. package/lib/typescript/components/PlatformToggle.d.ts +0 -20
  561. package/lib/typescript/components/PlatformToggle.d.ts.map +0 -1
  562. package/lib/typescript/components/PrimaryButton.d.ts +0 -22
  563. package/lib/typescript/components/PrimaryButton.d.ts.map +0 -1
  564. package/lib/typescript/components/SignInMatchAnimation.d.ts +0 -9
  565. package/lib/typescript/components/SignInMatchAnimation.d.ts.map +0 -1
  566. package/lib/typescript/components/SignInStep.d.ts +0 -12
  567. package/lib/typescript/components/SignInStep.d.ts.map +0 -1
  568. package/lib/typescript/components/VerificationStep.d.ts +0 -13
  569. package/lib/typescript/components/VerificationStep.d.ts.map +0 -1
  570. package/lib/typescript/components/WelcomeScreen.d.ts +0 -9
  571. package/lib/typescript/components/WelcomeScreen.d.ts.map +0 -1
  572. package/lib/typescript/components/icons/Basicproficon.d.ts +0 -5
  573. package/lib/typescript/components/icons/Basicproficon.d.ts.map +0 -1
  574. package/lib/typescript/components/icons/Basicprofile.d.ts +0 -5
  575. package/lib/typescript/components/icons/Basicprofile.d.ts.map +0 -1
  576. package/lib/typescript/components/icons/Checkbox.d.ts +0 -5
  577. package/lib/typescript/components/icons/Checkbox.d.ts.map +0 -1
  578. package/lib/typescript/components/icons/Checkmark.d.ts +0 -5
  579. package/lib/typescript/components/icons/Checkmark.d.ts.map +0 -1
  580. package/lib/typescript/components/icons/Contentanalysis.d.ts +0 -5
  581. package/lib/typescript/components/icons/Contentanalysis.d.ts.map +0 -1
  582. package/lib/typescript/components/icons/Contenticon.d.ts +0 -5
  583. package/lib/typescript/components/icons/Contenticon.d.ts.map +0 -1
  584. package/lib/typescript/components/icons/EnochE.d.ts +0 -5
  585. package/lib/typescript/components/icons/EnochE.d.ts.map +0 -1
  586. package/lib/typescript/components/icons/Personalityicon.d.ts +0 -5
  587. package/lib/typescript/components/icons/Personalityicon.d.ts.map +0 -1
  588. package/lib/typescript/components/icons/Personalityprofile.d.ts +0 -5
  589. package/lib/typescript/components/icons/Personalityprofile.d.ts.map +0 -1
  590. package/lib/typescript/components/icons/Personalitytraits.d.ts +0 -5
  591. package/lib/typescript/components/icons/Personalitytraits.d.ts.map +0 -1
  592. package/lib/typescript/components/icons/Userpreferences.d.ts +0 -5
  593. package/lib/typescript/components/icons/Userpreferences.d.ts.map +0 -1
  594. package/lib/typescript/components/icons/index.d.ts +0 -12
  595. package/lib/typescript/components/icons/index.d.ts.map +0 -1
  596. package/lib/typescript/config/api.d.ts +0 -24
  597. package/lib/typescript/config/api.d.ts.map +0 -1
  598. package/lib/typescript/context/AuthContext.d.ts +0 -34
  599. package/lib/typescript/context/AuthContext.d.ts.map +0 -1
  600. package/lib/typescript/hooks/useConnectedAccounts.d.ts +0 -11
  601. package/lib/typescript/hooks/useConnectedAccounts.d.ts.map +0 -1
  602. package/lib/typescript/hooks/useUserConnections.d.ts +0 -12
  603. package/lib/typescript/hooks/useUserConnections.d.ts.map +0 -1
  604. package/lib/typescript/services/apiClient.d.ts +0 -91
  605. package/lib/typescript/services/apiClient.d.ts.map +0 -1
  606. package/lib/typescript/services/authService.d.ts +0 -216
  607. package/lib/typescript/services/authService.d.ts.map +0 -1
  608. package/lib/typescript/services/biometricPinService.d.ts +0 -29
  609. package/lib/typescript/services/biometricPinService.d.ts.map +0 -1
  610. package/lib/typescript/services/connectedAccountsService.d.ts +0 -56
  611. package/lib/typescript/services/connectedAccountsService.d.ts.map +0 -1
  612. package/lib/typescript/services/googleAuthService.d.ts +0 -63
  613. package/lib/typescript/services/googleAuthService.d.ts.map +0 -1
  614. package/lib/typescript/services/imageCompressionService.d.ts +0 -37
  615. package/lib/typescript/services/imageCompressionService.d.ts.map +0 -1
  616. package/lib/typescript/services/jwtStorageService.d.ts +0 -86
  617. package/lib/typescript/services/jwtStorageService.d.ts.map +0 -1
  618. package/lib/typescript/services/mobileTrainingService.d.ts +0 -45
  619. package/lib/typescript/services/mobileTrainingService.d.ts.map +0 -1
  620. package/lib/typescript/services/pinEncryptionService.d.ts +0 -17
  621. package/lib/typescript/services/pinEncryptionService.d.ts.map +0 -1
  622. package/lib/typescript/services/pinStorageUtils.d.ts +0 -25
  623. package/lib/typescript/services/pinStorageUtils.d.ts.map +0 -1
  624. package/lib/typescript/services/storageService.d.ts +0 -128
  625. package/lib/typescript/services/storageService.d.ts.map +0 -1
  626. package/lib/typescript/services/trainingApiHelpers.d.ts +0 -38
  627. package/lib/typescript/services/trainingApiHelpers.d.ts.map +0 -1
  628. package/lib/typescript/services/userConnectionsService.d.ts +0 -90
  629. package/lib/typescript/services/userConnectionsService.d.ts.map +0 -1
  630. package/lib/typescript/services/youtubeMigrationService.d.ts +0 -12
  631. package/lib/typescript/services/youtubeMigrationService.d.ts.map +0 -1
  632. package/lib/typescript/theme/index.d.ts +0 -416
  633. package/lib/typescript/theme/index.d.ts.map +0 -1
  634. package/lib/typescript/utils/eventUtils.d.ts +0 -108
  635. package/lib/typescript/utils/eventUtils.d.ts.map +0 -1
  636. package/lib/typescript/utils/haptics.d.ts +0 -11
  637. package/lib/typescript/utils/haptics.d.ts.map +0 -1
  638. package/lib/typescript/utils/imagePreloader.d.ts +0 -2
  639. package/lib/typescript/utils/imagePreloader.d.ts.map +0 -1
  640. package/src/assets/fonts/EBGaramond-VariableFont_wght.ttf +0 -0
  641. package/src/assets/fonts/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
  642. package/src/assets/icons/Facebookicon.png +0 -0
  643. package/src/assets/icons/Gmail.png +0 -0
  644. package/src/assets/icons/Linkedinicon.png +0 -0
  645. package/src/assets/icons/Redditicon.png +0 -0
  646. package/src/assets/icons/YouTubeicon2.png +0 -0
  647. package/src/assets/icons/YouTubeicon3.png +0 -0
  648. package/src/assets/icons/farcaster.png +0 -0
  649. package/src/assets/icons/instagram.png +0 -0
  650. package/src/assets/icons/pinterest.png +0 -0
  651. package/src/assets/icons/swerv_logo.png +0 -0
  652. package/src/assets/icons/twitter.jpg +0 -0
  653. package/src/assets/images/Checkbox.svg +0 -3
  654. package/src/assets/images/EnochE.svg +0 -19
  655. package/src/assets/images/Enochicon1.png +0 -0
  656. package/src/assets/images/Face_ID_logo.png +0 -0
  657. package/src/assets/images/Facebookicon.png +0 -0
  658. package/src/assets/images/Gmail.png +0 -0
  659. package/src/assets/images/Googlelogo.png +0 -0
  660. package/src/assets/images/Linkedinicon.png +0 -0
  661. package/src/assets/images/Onairoslogo.png +0 -0
  662. package/src/assets/images/Personalityprofile.svg +0 -3
  663. package/src/assets/images/Personalitytraits.svg +0 -3
  664. package/src/assets/images/Redditicon.png +0 -0
  665. package/src/assets/images/Userpreferences.svg +0 -3
  666. package/src/assets/images/YouTubeicon3.png +0 -0
  667. package/src/assets/images/arrow.svg +0 -20
  668. package/src/assets/images/basicproficon.svg +0 -43
  669. package/src/assets/images/basicprofile.svg +0 -3
  670. package/src/assets/images/checkmark.svg +0 -4
  671. package/src/assets/images/contentanalysis.svg +0 -3
  672. package/src/assets/images/contenticon.svg +0 -23
  673. package/src/assets/images/persona1.png +0 -0
  674. package/src/assets/images/persona2.png +0 -0
  675. package/src/assets/images/persona3.png +0 -0
  676. package/src/assets/images/persona4.png +0 -0
  677. package/src/assets/images/persona5.png +0 -0
  678. package/src/assets/images/personalityicon.svg +0 -18
  679. package/src/assets/images/x-close.svg +0 -3
  680. package/src/components/BodyText.tsx +0 -33
  681. package/src/components/BrandMark.tsx +0 -62
  682. package/src/components/CodeInput.tsx +0 -32
  683. package/src/components/EmailInput.tsx +0 -31
  684. package/src/components/ExistingUserDataConfirmation.tsx +0 -507
  685. package/src/components/GoogleButton.tsx +0 -55
  686. package/src/components/HeadingGroup.tsx +0 -49
  687. package/src/components/ModalHeader.tsx +0 -125
  688. package/src/components/ModalSheet.tsx +0 -59
  689. package/src/components/OnairosSignInButton.tsx +0 -132
  690. package/src/components/PersonaImage.tsx +0 -79
  691. package/src/components/PersonaLoadingScreen.tsx +0 -201
  692. package/src/components/PersonalizationConsentScreen.tsx +0 -410
  693. package/src/components/PinCreationScreen.tsx +0 -492
  694. package/src/components/PlatformConnectorsStep.tsx +0 -892
  695. package/src/components/PlatformToggle.tsx +0 -226
  696. package/src/components/PrimaryButton.tsx +0 -214
  697. package/src/components/SignInMatchAnimation.tsx +0 -225
  698. package/src/components/SignInStep.tsx +0 -217
  699. package/src/components/VerificationStep.tsx +0 -198
  700. package/src/components/WelcomeScreen.tsx +0 -490
  701. package/src/components/icons/Basicproficon.tsx +0 -30
  702. package/src/components/icons/Basicprofile.tsx +0 -17
  703. package/src/components/icons/Checkbox.tsx +0 -17
  704. package/src/components/icons/Checkmark.tsx +0 -24
  705. package/src/components/icons/Contentanalysis.tsx +0 -17
  706. package/src/components/icons/Contenticon.tsx +0 -30
  707. package/src/components/icons/EnochE.tsx +0 -39
  708. package/src/components/icons/Personalityicon.tsx +0 -22
  709. package/src/components/icons/Personalityprofile.tsx +0 -17
  710. package/src/components/icons/Personalitytraits.tsx +0 -17
  711. package/src/components/icons/Userpreferences.tsx +0 -17
  712. package/src/components/icons/index.ts +0 -12
  713. package/src/config/api.ts +0 -25
  714. package/src/context/AuthContext.tsx +0 -393
  715. package/src/hooks/useConnectedAccounts.ts +0 -139
  716. package/src/hooks/useUserConnections.ts +0 -166
  717. package/src/services/apiClient.ts +0 -337
  718. package/src/services/authService.ts +0 -1008
  719. package/src/services/biometricPinService.ts +0 -193
  720. package/src/services/connectedAccountsService.ts +0 -290
  721. package/src/services/googleAuthService.ts +0 -279
  722. package/src/services/imageCompressionService.ts +0 -303
  723. package/src/services/jwtStorageService.ts +0 -257
  724. package/src/services/mobileTrainingService.ts +0 -204
  725. package/src/services/pinEncryptionService.ts +0 -76
  726. package/src/services/pinStorageUtils.ts +0 -97
  727. package/src/services/storageService.ts +0 -452
  728. package/src/services/trainingApiHelpers.ts +0 -67
  729. package/src/services/userConnectionsService.ts +0 -557
  730. package/src/services/youtubeMigrationService.ts +0 -454
  731. package/src/theme/index.ts +0 -239
  732. package/src/utils/eventUtils.ts +0 -303
  733. package/src/utils/haptics.ts +0 -59
  734. package/src/utils/imagePreloader.ts +0 -2
@@ -1,1346 +1,1113 @@
1
- /**
2
- * Platform Authentication Service
3
- * Handles OAuth flows for different platforms
4
- */
5
-
6
- import { Platform, Linking } from 'react-native';
7
- import { GoogleSignin, statusCodes } from '@react-native-google-signin/google-signin';
8
- import AsyncStorage from '@react-native-async-storage/async-storage';
9
- import { API_CONFIG, getApiHeaders, getAuthHeaders } from '../config/api';
10
-
11
- // ๐Ÿ”‘ CRITICAL: Using the same client ID for both web and iOS to avoid audience errors
12
- const WEB_CLIENT_ID = '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com';
13
- const IOS_CLIENT_ID = '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com';
14
-
15
- type OAuthConfig = {
16
- [key: string]: {
17
- authUrl?: string;
18
- clientId?: string;
19
- redirectUri?: string;
20
- scope?: string;
21
- responseType?: string;
22
- hasNativeSDK: boolean;
23
- };
24
- };
25
-
26
- // OAuth configuration for different platforms
27
- const OAUTH_CONFIG: OAuthConfig = {
28
- instagram: {
29
- authUrl: 'https://api.instagram.com/oauth/authorize',
30
- clientId: 'demo_instagram_client_id',
31
- redirectUri: 'onairosevents://auth/callback',
32
- scope: 'user_profile,user_media',
33
- responseType: 'code',
34
- hasNativeSDK: false
35
- },
36
- youtube: {
37
- authUrl: 'https://api2.onairos.uk/youtube/authorize',
38
- clientId: '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com',
39
- redirectUri: 'onairosevents://auth/callback',
40
- scope: 'https://www.googleapis.com/auth/youtube.readonly',
41
- responseType: 'code',
42
- hasNativeSDK: true // Changed to true for native SDK
43
- },
44
- reddit: {
45
- authUrl: 'https://api2.onairos.uk/reddit/authorize',
46
- clientId: 'demo_reddit_client_id',
47
- redirectUri: 'onairosevents://auth/callback',
48
- scope: 'identity,read',
49
- responseType: 'code',
50
- hasNativeSDK: false
51
- },
52
- pinterest: {
53
- authUrl: 'https://api2.onairos.uk/pinterest/authorize',
54
- clientId: 'demo_pinterest_client_id',
55
- redirectUri: 'onairosevents://auth/callback',
56
- scope: 'boards:read,pins:read',
57
- responseType: 'code',
58
- hasNativeSDK: false
59
- },
60
- facebook: {
61
- authUrl: 'https://www.facebook.com/v12.0/dialog/oauth',
62
- clientId: 'demo_facebook_client_id',
63
- redirectUri: 'onairosevents://auth/callback',
64
- scope: 'public_profile,email',
65
- responseType: 'code',
66
- hasNativeSDK: false
67
- },
68
- // GitHub connector is temporarily commented out
69
- // github: {
70
- // authUrl: 'https://github.com/login/oauth/authorize',
71
- // clientId: 'demo_github_client_id',
72
- // redirectUri: 'onairosevents://auth/callback',
73
- // scope: 'repo,user',
74
- // responseType: 'code',
75
- // hasNativeSDK: false
76
- // },
77
- linkedin: {
78
- authUrl: 'https://api2.onairos.uk/linkedin/authorize',
79
- clientId: '', // No client ID needed - backend handles OAuth
80
- redirectUri: 'onairosevents://auth/callback',
81
- scope: 'openid profile email', // Updated to OpenID Connect scopes as per your backend
82
- responseType: 'code',
83
- hasNativeSDK: false // LinkedIn has no modern native SDK
84
- },
85
- gmail: {
86
- authUrl: 'https://api2.onairos.uk/gmail/authorize',
87
- clientId: 'demo_gmail_client_id',
88
- redirectUri: 'onairosevents://auth/callback',
89
- scope: 'https://www.googleapis.com/auth/gmail.readonly',
90
- responseType: 'code',
91
- hasNativeSDK: false
92
- },
93
- email: {
94
- // Email doesn't use OAuth but we still need to handle it in the flow
95
- hasNativeSDK: false,
96
- authUrl: 'https://api2.onairos.uk/email/authorize' // Proxy endpoint for email verification
97
- }
98
- };
99
-
100
- /**
101
- * Check if the platform has a native SDK
102
- */
103
- export const hasNativeSDK = (platform: string): boolean => {
104
- return OAUTH_CONFIG[platform]?.hasNativeSDK || false;
105
- };
106
-
107
- /**
108
- * Initiate OAuth flow for a platform
109
- */
110
- export const initiateOAuth = async (platform: string, username: string): Promise<string | null> => {
111
- try {
112
- console.log(`๐Ÿš€ [OAUTH] Starting OAuth for platform: ${platform}, username: "${username}"`);
113
-
114
- // Validate username
115
- if (!username || username.trim() === '') {
116
- console.error(`โŒ [OAUTH] Username is required for ${platform} OAuth`);
117
- return null;
118
- }
119
-
120
- // For platforms that don't need OAuth (like email), handle differently
121
- if (platform === 'email') {
122
- console.log('๐Ÿ“ง [OAUTH] Email platform selected, returning mock auth URL');
123
- return 'https://api2.onairos.uk/email/authorize?action=verify';
124
- }
125
-
126
- // Construct the proxy URL
127
- const proxyUrl = `https://api2.onairos.uk/${platform}/authorize`;
128
- console.log(`๐ŸŒ [OAUTH] Proxy URL: ${proxyUrl}`);
129
-
130
- const requestBody = {
131
- session: {
132
- username: username.trim(),
133
- platform: platform,
134
- timestamp: new Date().toISOString()
135
- }
136
- };
137
- console.log(`๐Ÿ“ค [OAUTH] Request body:`, requestBody);
138
- console.log(`๐Ÿ”‘ [OAUTH] Headers:`, getApiHeaders());
139
-
140
- // Make a POST request to the proxy
141
- const response = await fetch(proxyUrl, {
142
- method: 'POST',
143
- headers: getApiHeaders(),
144
- body: JSON.stringify(requestBody)
145
- });
146
-
147
- console.log(`๐Ÿ“ก [OAUTH] Response status: ${response.status} ${response.statusText}`);
148
-
149
- if (!response.ok) {
150
- const errorText = await response.text();
151
- console.error(`โŒ [OAUTH] Error initiating OAuth for ${platform}: ${response.status} - ${errorText}`);
152
- return null;
153
- }
154
-
155
- const data = await response.json();
156
- console.log(`๐Ÿ“‹ [OAUTH] Response data for ${platform}:`, data);
157
-
158
- // Get the authorization URL from the response
159
- // Different platforms might use different keys (e.g., pinterestURL, youtubeURL)
160
- const urlKey = `${platform}URL`;
161
- const authUrl = data[urlKey] || data.url || null;
162
-
163
- console.log(`๐Ÿ”— [OAUTH] Auth URL for ${platform} (key: ${urlKey}):`, authUrl);
164
- return authUrl;
165
- } catch (error) {
166
- console.error(`Error initiating OAuth for ${platform}:`, error);
167
- return null;
168
- }
169
- };
170
-
171
- /**
172
- * Initialize Google Sign-In configuration with enhanced refresh token support
173
- * Updated with CRITICAL parameters for refresh token generation
174
- */
175
- const initializeGoogleSignIn = () => {
176
- GoogleSignin.configure({
177
- webClientId: WEB_CLIENT_ID, // โœ… CRITICAL: Web client ID for refresh tokens
178
- iosClientId: IOS_CLIENT_ID, // โœ… iOS client ID for native auth
179
-
180
- // ๐Ÿ”‘ CRITICAL: These parameters are REQUIRED for refresh tokens
181
- offlineAccess: true, // โ† CRITICAL: Enables refresh tokens
182
- forceCodeForRefreshToken: true, // โ† CRITICAL: Forces refresh token generation
183
-
184
- // โœ… Enhanced scopes for YouTube
185
- scopes: [
186
- 'https://www.googleapis.com/auth/youtube.readonly',
187
- 'openid',
188
- 'profile',
189
- 'email'
190
- ],
191
-
192
- // โœ… Clear settings to avoid conflicts
193
- hostedDomain: '',
194
- accountName: '',
195
- });
196
- };
197
-
198
- /**
199
- * Force YouTube reconnection with consent screen to get refresh tokens
200
- * This is the key function to fix YouTube token expiry issues
201
- */
202
- export const forceYouTubeReconnectionWithConsent = async (username: string): Promise<boolean> => {
203
- try {
204
- console.log('๐Ÿ”„ FORCING fresh YouTube consent for refresh token...');
205
- console.log('๐Ÿ‘ค User:', username);
206
-
207
- // Step 1: โœ… CRITICAL: Complete sign out (clears all cached consent)
208
- try {
209
- await GoogleSignin.signOut();
210
- console.log('โœ… Signed out - consent cache cleared');
211
- } catch (signOutError) {
212
- console.log('โ„น๏ธ Sign out not needed:', signOutError);
213
- }
214
-
215
- // Step 2: โœ… CRITICAL: Clear cached tokens if available
216
- try {
217
- const existingTokens = await GoogleSignin.getTokens();
218
- if (existingTokens.accessToken) {
219
- await GoogleSignin.clearCachedAccessToken(existingTokens.accessToken);
220
- console.log('โœ… Token cache cleared');
221
- }
222
- } catch (clearError) {
223
- console.log('โ„น๏ธ No token cache to clear');
224
- }
225
-
226
- // Step 3: โœ… CRITICAL: Configure Google Sign-In for FORCED consent
227
- console.log('๐Ÿ”ง Configuring Google Sign-In for forced consent...');
228
- GoogleSignin.configure({
229
- webClientId: WEB_CLIENT_ID, // โœ… CRITICAL: Web client ID for refresh tokens
230
- iosClientId: IOS_CLIENT_ID, // โœ… iOS client ID for native auth
231
-
232
- // ๐Ÿ”‘ FORCE REFRESH TOKEN SETTINGS:
233
- offlineAccess: true, // Request offline access
234
- forceCodeForRefreshToken: true, // Force refresh token generation
235
-
236
- // ๐Ÿ”‘ FORCE CONSENT SCREEN:
237
- scopes: [
238
- 'https://www.googleapis.com/auth/youtube.readonly',
239
- 'openid',
240
- 'profile',
241
- 'email'
242
- ],
243
-
244
- // โœ… CRITICAL: Clear settings to force fresh consent
245
- hostedDomain: '',
246
- accountName: '',
247
- });
248
-
249
- // Step 4: โœ… Check Play Services
250
- await GoogleSignin.hasPlayServices();
251
- console.log('โœ… Play Services available');
252
-
253
- // Step 5: โœ… CRITICAL: Sign in (this SHOULD show consent screen)
254
- console.log('๐Ÿ” Initiating sign-in - consent screen should appear...');
255
- console.log('๐Ÿ“ฑ User should see: "Allow [App] to access your YouTube account when you\'re not using the app?"');
256
-
257
- const userInfo = await GoogleSignin.signIn();
258
- console.log('โœ… Sign-in completed - checking for refresh token...');
259
- console.log('๐Ÿ‘ค User email:', userInfo.data?.user?.email);
260
-
261
- // Step 6: โœ… Get tokens after consent
262
- const tokens = await GoogleSignin.getTokens();
263
- const currentUser = await GoogleSignin.getCurrentUser();
264
-
265
- console.log('๐Ÿ“‹ FULL userInfo object from forceYouTubeReconnectionWithConsent:');
266
- console.log(JSON.stringify(userInfo, null, 2));
267
-
268
- console.log('๐Ÿ“‹ FULL tokens object from forceYouTubeReconnectionWithConsent:');
269
- console.log(JSON.stringify(tokens, null, 2));
270
-
271
- console.log('๐Ÿ“‹ FULL currentUser object from forceYouTubeReconnectionWithConsent:');
272
- console.log(JSON.stringify(currentUser, null, 2));
273
-
274
- console.log('๐Ÿ” Token analysis:');
275
- console.log('- Access token:', tokens.accessToken ? `${tokens.accessToken.substring(0, 20)}...` : 'Missing');
276
- console.log('- ID token:', tokens.idToken ? 'Present' : 'Missing');
277
- console.log('- ServerAuthCode (userInfo):', userInfo.data?.serverAuthCode ? `${userInfo.data.serverAuthCode.substring(0, 20)}...` : 'Missing');
278
- console.log('- ServerAuthCode (currentUser):', currentUser?.serverAuthCode ? `${currentUser.serverAuthCode.substring(0, 20)}...` : 'Missing');
279
-
280
- // Step 7: โœ… Extract refresh capability
281
- const refreshToken = userInfo.data?.serverAuthCode || currentUser?.serverAuthCode;
282
-
283
- if (refreshToken) {
284
- console.log('โœ… SUCCESS: Got refresh token after consent!');
285
- console.log('๐Ÿ”‘ Refresh token type:', refreshToken.startsWith('4/') ? 'serverAuthCode' : 'refreshToken');
286
- console.log('๐Ÿ”‘ Refresh token preview:', `${refreshToken.substring(0, 20)}...`);
287
-
288
- // Step 8: โœ… Get YouTube channel info
289
- let channelName = 'Unknown Channel';
290
- let channelId = null;
291
-
292
- try {
293
- console.log('๐Ÿ“บ Fetching YouTube channel information...');
294
- const channelResponse = await fetch('https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true', {
295
- headers: {
296
- 'Authorization': `Bearer ${tokens.accessToken}`,
297
- 'Accept': 'application/json'
298
- }
299
- });
300
-
301
- if (channelResponse.ok) {
302
- const channelData = await channelResponse.json();
303
- if (channelData.items && channelData.items.length > 0) {
304
- channelName = channelData.items[0].snippet.title;
305
- channelId = channelData.items[0].id;
306
- console.log('โœ… YouTube channel found:', channelName, 'ID:', channelId);
307
- } else {
308
- console.log('โš ๏ธ No YouTube channel found for user');
309
- channelName = userInfo.data?.user?.name || userInfo.data?.user?.email || 'No Channel';
310
- }
311
- } else {
312
- console.log('โš ๏ธ Failed to fetch YouTube channel info:', channelResponse.status);
313
- channelName = userInfo.data?.user?.name || userInfo.data?.user?.email || 'Unknown Channel';
314
- }
315
- } catch (channelError) {
316
- console.log('โš ๏ธ Error fetching YouTube channel info:', channelError);
317
- channelName = userInfo.data?.user?.name || userInfo.data?.user?.email || 'Unknown Channel';
318
- }
319
-
320
- // Step 9: โœ… Get authentication token
321
- let authToken = await AsyncStorage.getItem('onairos_jwt_token') ||
322
- await AsyncStorage.getItem('enoch_token') ||
323
- await AsyncStorage.getItem('auth_token');
324
-
325
- if (!authToken || authToken.trim().length < 20) {
326
- console.log('๐Ÿ” Creating authentication token for YouTube connection...');
327
- // Create token logic here if needed
328
- authToken = 'temp_token_for_youtube_connection';
329
- }
330
-
331
- // Step 10: โœ… Send comprehensive data to backend
332
- const backendPayload = {
333
- session: {
334
- username: username,
335
- platform: 'youtube',
336
- timestamp: new Date().toISOString(),
337
- channelName: channelName,
338
- channelId: channelId,
339
- forceConsent: true // Flag to indicate this was forced consent
340
- },
341
- googleUser: userInfo.data?.user,
342
- accessToken: tokens.accessToken,
343
- idToken: tokens.idToken,
344
- refreshToken: refreshToken, // โœ… CRITICAL: The refresh token!
345
- serverAuthCode: refreshToken, // โœ… Same as refresh token
346
-
347
- // โœ… CRITICAL: Additional compatibility fields for backend
348
- refresh_token: refreshToken, // Snake case version
349
- server_auth_code: refreshToken, // Snake case version
350
- authCode: refreshToken, // Alternative naming
351
-
352
- userAccountInfo: {
353
- username: username,
354
- email: userInfo.data?.user?.email,
355
- authToken: authToken,
356
- channelName: channelName,
357
- channelId: channelId,
358
- userIdentifier: authToken ? `user-${authToken.substring(0, 10)}` : `youtube-${userInfo.data?.user?.email}`,
359
- googleId: userInfo.data?.user?.id,
360
- // โœ… CRITICAL: Also include refresh token in userAccountInfo
361
- refreshToken: refreshToken,
362
- serverAuthCode: refreshToken
363
- },
364
- tokenExpiry: new Date(Date.now() + 3600 * 1000).toISOString(), // 1 hour from now
365
- requestRefreshToken: true,
366
- debugInfo: {
367
- hasRefreshToken: true,
368
- refreshTokenType: refreshToken.startsWith('4/') ? 'serverAuthCode' : 'refreshToken',
369
- configuredForRefresh: true,
370
- forcedConsent: true,
371
- consentMethod: 'signOut_and_configure',
372
- refreshTokenValue: refreshToken // Include actual value for debugging
373
- }
374
- };
375
-
376
- console.log('๐Ÿ“ค Sending comprehensive payload with REFRESH TOKEN to backend:', {
377
- hasAccessToken: !!backendPayload.accessToken,
378
- hasRefreshToken: !!backendPayload.refreshToken,
379
- hasServerAuthCode: !!backendPayload.serverAuthCode,
380
- refreshTokenType: backendPayload.debugInfo.refreshTokenType,
381
- userEmail: userInfo.data?.user?.email,
382
- forcedConsent: true
383
- });
384
-
385
- // Step 11: โœ… Send to backend with ENHANCED LOGGING
386
- console.log('๐Ÿš€ [YOUTUBE REAUTH] ===== SENDING REAUTH SIGNAL TO BACKEND =====');
387
- console.log('๐Ÿš€ [YOUTUBE REAUTH] Endpoint: https://api2.onairos.uk/youtube/native-auth');
388
- console.log('๐Ÿš€ [YOUTUBE REAUTH] Method: POST');
389
- console.log('๐Ÿš€ [YOUTUBE REAUTH] Headers:', {
390
- 'Content-Type': 'application/json',
391
- 'Authorization': authToken ? `${authToken.substring(0, 20)}...` : 'NO AUTH TOKEN'
392
- });
393
- console.log('๐Ÿš€ [YOUTUBE REAUTH] Payload Summary:', {
394
- hasAccessToken: !!backendPayload.accessToken,
395
- hasRefreshToken: !!backendPayload.refreshToken,
396
- hasServerAuthCode: !!backendPayload.serverAuthCode,
397
- refreshTokenType: backendPayload.debugInfo.refreshTokenType,
398
- userEmail: userInfo.data?.user?.email,
399
- channelName: channelName,
400
- forcedConsent: true,
401
- requestRefreshToken: true
402
- });
403
- console.log('๐Ÿš€ [YOUTUBE REAUTH] FULL PAYLOAD:', JSON.stringify(backendPayload, null, 2));
404
-
405
-
406
-
407
- const backendResponse = await fetch('https://api2.onairos.uk/youtube/native-auth', {
408
- method: 'POST',
409
- headers: {
410
- 'Content-Type': 'application/json',
411
- ...(authToken && { 'Authorization': authToken })
412
- },
413
- body: JSON.stringify(backendPayload)
414
- });
415
-
416
- console.log('๐Ÿ“ก [YOUTUBE REAUTH] Response Status:', backendResponse.status);
417
- console.log('๐Ÿ“ก [YOUTUBE REAUTH] Response Status Text:', backendResponse.statusText);
418
- console.log('๐Ÿ“ก [YOUTUBE REAUTH] Response Headers:', backendResponse.headers);
419
-
420
- if (backendResponse.ok) {
421
- const responseData = await backendResponse.json();
422
- console.log('โœ… [YOUTUBE REAUTH] Backend Response SUCCESS:', JSON.stringify(responseData, null, 2));
423
-
424
- // Enhanced verification with detailed logging and temporary mode detection (exact backend fields)
425
- const isTemporaryMode = responseData.validation?.isTemporaryMode === true ||
426
- responseData.temporaryMode?.enabled === true ||
427
- responseData.isTemporaryMode === true ||
428
- (responseData.message && responseData.message.includes('temporary access token mode'));
429
-
430
- if (isTemporaryMode) {
431
- console.log('๐Ÿ”„ [YOUTUBE REAUTH] YouTube connected in temporary mode');
432
- console.log('โœ… [YOUTUBE REAUTH] Training will work, but connection expires in ~1 hour');
433
- console.log('๐ŸŽ‰ [YOUTUBE REAUTH] SUCCESS: Temporary YouTube connection established!');
434
-
435
- console.log('๐Ÿ”‘ [YOUTUBE REAUTH] Connection Details:');
436
- console.log('๐Ÿ”‘ [YOUTUBE REAUTH] Mode: Temporary (expires ~1 hour)');
437
- console.log('๐Ÿ”‘ [YOUTUBE REAUTH] Training Ready: Yes');
438
- console.log('๐Ÿ”‘ [YOUTUBE REAUTH] Refresh token sent:', refreshToken ? 'Yes' : 'No');
439
- } else if (responseData.hasRefreshToken || responseData.refreshTokenReceived) {
440
- console.log('โœ… [YOUTUBE REAUTH] Backend CONFIRMED refresh token received');
441
- console.log('โœ… [YOUTUBE REAUTH] Response hasRefreshToken:', responseData.hasRefreshToken);
442
- console.log('๐ŸŽ‰ [YOUTUBE REAUTH] SUCCESS: Full YouTube connection with refresh tokens!');
443
-
444
- // CRITICAL: Print the refresh token that was sent for debugging
445
- console.log('๐Ÿ”‘ [YOUTUBE REAUTH] REFRESH TOKEN SENT TO BACKEND:');
446
- console.log('๐Ÿ”‘ [YOUTUBE REAUTH] Full refresh token:', refreshToken);
447
- console.log('๐Ÿ”‘ [YOUTUBE REAUTH] Refresh token type:', refreshToken.startsWith('4/') ? 'serverAuthCode' : 'refreshToken');
448
- console.log('๐Ÿ”‘ [YOUTUBE REAUTH] Refresh token length:', refreshToken.length);
449
- } else {
450
- console.warn('โš ๏ธ [YOUTUBE REAUTH] Backend did NOT confirm refresh token reception');
451
- console.warn('โš ๏ธ [YOUTUBE REAUTH] Response data:', responseData);
452
- console.warn('โš ๏ธ [YOUTUBE REAUTH] Expected hasRefreshToken or refreshTokenReceived in response');
453
- return false;
454
- }
455
-
456
- // CRITICAL: Signal training system to restart with new connection
457
- console.log('๐Ÿ”„ [YOUTUBE REAUTH] Signaling training system to restart...');
458
- try {
459
- await triggerTrainingRestart(username, authToken);
460
- console.log('โœ… [YOUTUBE REAUTH] Training restart signal sent successfully');
461
- } catch (restartError) {
462
- console.warn('โš ๏ธ [YOUTUBE REAUTH] Training restart signal failed:', restartError);
463
- console.warn('โš ๏ธ [YOUTUBE REAUTH] User may need to manually restart training');
464
- }
465
-
466
- return true;
467
- } else {
468
- const errorData = await backendResponse.text();
469
- console.error('โŒ [YOUTUBE REAUTH] Backend processing FAILED:', backendResponse.status, errorData);
470
- console.error('โŒ [YOUTUBE REAUTH] This means the reauth signal was not processed');
471
- return false;
472
- }
473
-
474
- } else {
475
- console.error('โŒ CRITICAL: No refresh token even after consent screen');
476
- console.error('โŒ This means consent screen did not appear or user denied permissions');
477
- console.error('๐Ÿ’ก Solutions:');
478
- console.error(' 1. Try the revoke method: forceYouTubeReconnectionWithRevoke()');
479
- console.error(' 2. Check Google Console OAuth configuration');
480
- console.error(' 3. Ensure user clicks "Allow" on consent screen');
481
- return false;
482
- }
483
-
484
- } catch (error: any) {
485
- console.error('โŒ Error forcing YouTube consent:', error);
486
-
487
- if (error.code === statusCodes.SIGN_IN_CANCELLED) {
488
- console.error('โŒ User cancelled sign-in - no refresh token obtained');
489
- console.error('๐Ÿ’ก User must click "Allow" to get refresh token');
490
- } else if (error.code === statusCodes.IN_PROGRESS) {
491
- console.error('โŒ Sign-in already in progress');
492
- } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
493
- console.error('โŒ Google Play Services not available');
494
- }
495
-
496
- return false;
497
- }
498
- };
499
-
500
- /**
501
- * Alternative method: Force consent by revoking existing permissions
502
- */
503
- export const forceYouTubeReconnectionWithRevoke = async (username: string): Promise<boolean> => {
504
- try {
505
- console.log('๐Ÿ”„ FORCING YouTube consent via REVOKE method...');
506
- console.log('๐Ÿ‘ค User:', username);
507
-
508
- // Step 1: Initialize Google Sign-In
509
- initializeGoogleSignIn();
510
- await GoogleSignin.hasPlayServices();
511
-
512
- // Step 2: โœ… CRITICAL: Revoke existing permissions (forces fresh consent)
513
- try {
514
- await GoogleSignin.revokeAccess();
515
- console.log('โœ… Revoked existing permissions - fresh consent REQUIRED');
516
- } catch (revokeError) {
517
- console.log('โ„น๏ธ No existing permissions to revoke:', revokeError);
518
- }
519
-
520
- // Step 3: Sign out completely
521
- await GoogleSignin.signOut();
522
- console.log('โœ… Signed out completely');
523
-
524
- // Step 4: โœ… Now sign in again (will DEFINITELY show consent screen)
525
- console.log('๐Ÿ” Signing in after revoke - consent screen MUST appear...');
526
- const userInfo = await GoogleSignin.signIn();
527
-
528
- // Step 5: โœ… User will definitely see consent screen now
529
- const tokens = await GoogleSignin.getTokens();
530
- const currentUser = await GoogleSignin.getCurrentUser();
531
- const refreshToken = userInfo.data?.serverAuthCode || currentUser?.serverAuthCode;
532
-
533
- if (refreshToken) {
534
- console.log('โœ… SUCCESS: Got refresh token after REVOKE + consent!');
535
- console.log('๐Ÿ”‘ Refresh token preview:', `${refreshToken.substring(0, 20)}...`);
536
-
537
- // Continue with the same backend submission logic as above
538
- // (Similar to forceYouTubeReconnectionWithConsent)
539
-
540
- return true;
541
- } else {
542
- console.error('โŒ Still no refresh token after revoke method');
543
- return false;
544
- }
545
-
546
- } catch (error) {
547
- console.error('โŒ Error with revoke method:', error);
548
- return false;
549
- }
550
- };
551
-
552
- /**
553
- * Fix YouTube connection for a specific user (like nicholase50)
554
- */
555
- export const fixUserYouTubeConnection = async (username: string): Promise<boolean> => {
556
- console.log(`๐Ÿ”ง Fixing YouTube connection for user: ${username}`);
557
-
558
- // Method 1: Try forced consent via configuration
559
- console.log('๐Ÿ”„ Method 1: Trying forced consent via configuration...');
560
- let success = await forceYouTubeReconnectionWithConsent(username);
561
-
562
- if (success) {
563
- console.log(`โœ… ${username} YouTube connection fixed via Method 1!`);
564
- return true;
565
- }
566
-
567
- // Method 2: Try forced consent via revoke
568
- console.log('๐Ÿ”„ Method 2: Trying forced consent via revoke...');
569
- success = await forceYouTubeReconnectionWithRevoke(username);
570
-
571
- if (success) {
572
- console.log(`โœ… ${username} YouTube connection fixed via Method 2!`);
573
- return true;
574
- }
575
-
576
- console.error(`โŒ Failed to fix ${username} YouTube connection with both methods`);
577
- return false;
578
- };
579
-
580
- /**
581
- * Get fresh tokens using refresh token
582
- */
583
- const refreshGoogleTokens = async (): Promise<{ accessToken: string; idToken?: string } | null> => {
584
- try {
585
- console.log('๐Ÿ”„ Attempting to refresh Google tokens...');
586
-
587
- // Check if user is signed in
588
- const currentUser = await GoogleSignin.getCurrentUser();
589
- if (!currentUser) {
590
- console.log('โŒ User not signed in to Google, cannot refresh tokens');
591
- return null;
592
- }
593
-
594
- // Get fresh tokens
595
- const tokens = await GoogleSignin.getTokens();
596
- console.log('โœ… Successfully refreshed Google tokens');
597
-
598
- return {
599
- accessToken: tokens.accessToken,
600
- idToken: tokens.idToken
601
- };
602
- } catch (error) {
603
- console.error('โŒ Failed to refresh Google tokens:', error);
604
-
605
- // If refresh fails, try to sign in again
606
- try {
607
- console.log('๐Ÿ”„ Refresh failed, attempting re-authentication...');
608
- const userInfo = await GoogleSignin.signIn();
609
- const tokens = await GoogleSignin.getTokens();
610
-
611
- console.log('โœ… Re-authentication successful');
612
- return {
613
- accessToken: tokens.accessToken,
614
- idToken: tokens.idToken
615
- };
616
- } catch (signInError) {
617
- console.error('โŒ Re-authentication also failed:', signInError);
618
- return null;
619
- }
620
- }
621
- };
622
-
623
- /**
624
- * Debug YouTube tokens to verify refresh token availability
625
- */
626
- const debugYouTubeTokens = async (): Promise<{ hasRefreshToken: boolean; refreshTokenType: string }> => {
627
- try {
628
- const tokens = await GoogleSignin.getTokens();
629
- const currentUser = await GoogleSignin.getCurrentUser();
630
-
631
- console.log('๐Ÿ” YouTube Token Debug:', {
632
- accessToken: tokens.accessToken ? `${tokens.accessToken.substring(0, 20)}...` : 'Missing',
633
- idToken: tokens.idToken ? 'Present' : 'Missing',
634
- serverAuthCode: currentUser?.serverAuthCode ? `${currentUser.serverAuthCode.substring(0, 20)}...` : 'Missing',
635
- userEmail: currentUser?.user?.email || 'Missing'
636
- });
637
-
638
- return {
639
- hasRefreshToken: !!(currentUser?.serverAuthCode),
640
- refreshTokenType: currentUser?.serverAuthCode ? 'serverAuthCode' : 'none'
641
- };
642
- } catch (error) {
643
- console.error('โŒ Debug tokens failed:', error);
644
- return { hasRefreshToken: false, refreshTokenType: 'error' };
645
- }
646
- };
647
-
648
- /**
649
- * Force fresh YouTube reconnection with proper refresh token
650
- */
651
- export const reconnectYouTube = async (username: string): Promise<boolean> => {
652
- try {
653
- console.log('๐Ÿ”„ Forcing fresh YouTube reconnection for refresh token...');
654
-
655
- // 1. Sign out completely to force fresh consent
656
- try {
657
- await GoogleSignin.signOut();
658
- console.log('โœ… Signed out from Google');
659
- } catch (signOutError) {
660
- console.log('โ„น๏ธ Already signed out or sign out failed:', signOutError);
661
- }
662
-
663
- // 2. Clear any cached tokens
664
- try {
665
- const currentTokens = await GoogleSignin.getTokens();
666
- if (currentTokens.accessToken) {
667
- await GoogleSignin.clearCachedAccessToken(currentTokens.accessToken);
668
- console.log('โœ… Cleared cached access token');
669
- }
670
- } catch (clearError) {
671
- console.log('โ„น๏ธ Token clearing failed or not needed:', clearError);
672
- }
673
-
674
- // 3. Re-authenticate with fresh consent
675
- const result = await initiateNativeAuth('youtube', username);
676
-
677
- if (result) {
678
- console.log('โœ… YouTube reconnected successfully with refresh token');
679
-
680
- // 4. Verify we now have a refresh token
681
- const debugInfo = await debugYouTubeTokens();
682
- if (debugInfo.hasRefreshToken) {
683
- console.log('โœ… Refresh token confirmed:', debugInfo.refreshTokenType);
684
- } else {
685
- console.warn('โš ๏ธ Still no refresh token after reconnection');
686
- }
687
-
688
- return true;
689
- } else {
690
- console.error('โŒ YouTube reconnection failed');
691
- return false;
692
- }
693
- } catch (error) {
694
- console.error('โŒ YouTube reconnection error:', error);
695
- return false;
696
- }
697
- };
698
-
699
- /**
700
- * Initiate native authentication for platforms with SDKs
701
- */
702
- export const initiateNativeAuth = async (platform: string, username?: string): Promise<boolean> => {
703
- if (platform === 'youtube') {
704
- console.log('๐Ÿ”— Initiating native Google Sign-In for YouTube');
705
-
706
- // Validate username for YouTube
707
- if (!username || username.trim() === '') {
708
- console.error('โŒ [YOUTUBE AUTH] Username is required for YouTube authentication');
709
- return false;
710
- }
711
-
712
- try {
713
- // Initialize Google Sign-In if not already done
714
- // โœ… CRITICAL: Initialize with CORRECT iOS Client ID
715
- initializeGoogleSignIn();
716
-
717
- // Check if Google Play Services are available
718
- await GoogleSignin.hasPlayServices();
719
-
720
- // โœ… CRITICAL: Force sign out first to ensure fresh consent
721
- try {
722
- await GoogleSignin.signOut();
723
- console.log('๐Ÿ”„ Signed out to force fresh consent');
724
- } catch (signOutError) {
725
- console.log('โ„น๏ธ Sign out not needed or failed:', signOutError);
726
- }
727
-
728
- // Sign in with Google (this will show consent screen due to our config)
729
- const userInfo = await GoogleSignin.signIn();
730
- console.log('โœ… Google Sign-In successful:', userInfo.data?.user?.email);
731
-
732
- console.log('๐Ÿ“‹ FULL userInfo object:');
733
- console.log(JSON.stringify(userInfo, null, 2));
734
-
735
- // Get access token for API calls
736
- const tokens = await GoogleSignin.getTokens();
737
- console.log('๐Ÿ”‘ Got Google tokens');
738
- console.log('๐Ÿ“‹ FULL tokens object:');
739
- console.log(JSON.stringify(tokens, null, 2));
740
-
741
- // CRITICAL: Get the current user info which contains the refresh token
742
- const currentUser = await GoogleSignin.getCurrentUser();
743
- console.log('๐Ÿ‘ค Current user info:', currentUser?.user?.email);
744
- console.log('๐Ÿ“‹ FULL currentUser object:');
745
- console.log(JSON.stringify(currentUser, null, 2));
746
-
747
- // โœ… CRITICAL: Extract refresh token properly using serverAuthCode
748
- let refreshToken = null;
749
-
750
- console.log('๐Ÿ” REFRESH TOKEN EXTRACTION:');
751
- console.log('- userInfo.data?.serverAuthCode:', userInfo.data?.serverAuthCode ? `Present: ${userInfo.data.serverAuthCode.substring(0, 20)}...` : 'Missing');
752
- console.log('- currentUser?.serverAuthCode:', currentUser?.serverAuthCode ? `Present: ${currentUser.serverAuthCode.substring(0, 20)}...` : 'Missing');
753
- console.log('- tokens.idToken:', tokens.idToken ? `Present: ${tokens.idToken.substring(0, 20)}...` : 'Missing');
754
- console.log('- tokens.accessToken:', tokens.accessToken ? `Present: ${tokens.accessToken.substring(0, 20)}...` : 'Missing');
755
-
756
- // The serverAuthCode is the refresh token mechanism for React Native Google Sign-In
757
- if (currentUser?.serverAuthCode) {
758
- refreshToken = currentUser.serverAuthCode;
759
- console.log('โœ… Got serverAuthCode (refresh token mechanism)');
760
- console.log('๐Ÿ”‘ Refresh token preview:', `${refreshToken.substring(0, 20)}...`);
761
- } else if (userInfo.data?.serverAuthCode) {
762
- refreshToken = userInfo.data.serverAuthCode;
763
- console.log('โœ… Got serverAuthCode from sign-in response');
764
- console.log('๐Ÿ”‘ Refresh token preview:', `${refreshToken.substring(0, 20)}...`);
765
- }
766
-
767
- // โœ… CRITICAL: Verify refresh token availability
768
- if (!refreshToken) {
769
- console.error('โŒ CRITICAL: No refresh token available - YouTube connection will fail when token expires');
770
- console.error('๐Ÿ’ก User needs to reconnect with proper consent screen');
771
- console.error('๐Ÿ’ก Check Google Sign-In configuration: offlineAccess, forceCodeForRefreshToken');
772
-
773
- // Still continue but warn about the issue
774
- console.warn('โš ๏ธ Continuing without refresh token - connection may fail later');
775
- } else {
776
- console.log('โœ… Refresh token available for YouTube connection');
777
- console.log('๐Ÿ”‘ Refresh token type:', refreshToken.startsWith('4/') ? 'serverAuthCode' : 'refreshToken');
778
- }
779
-
780
- // Fetch YouTube channel information using the access token
781
- let channelName = 'Unknown Channel';
782
- let channelId = null;
783
- try {
784
- console.log('๐Ÿ“บ Fetching YouTube channel information...');
785
- const channelResponse = await fetch('https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true', {
786
- headers: {
787
- 'Authorization': `Bearer ${tokens.accessToken}`,
788
- 'Accept': 'application/json'
789
- }
790
- });
791
-
792
- if (channelResponse.ok) {
793
- const channelData = await channelResponse.json();
794
- if (channelData.items && channelData.items.length > 0) {
795
- channelName = channelData.items[0].snippet.title;
796
- channelId = channelData.items[0].id;
797
- console.log('โœ… YouTube channel found:', channelName, 'ID:', channelId);
798
- } else {
799
- console.log('โš ๏ธ No YouTube channel found for user');
800
- channelName = userInfo.data?.user?.name || userInfo.data?.user?.email || 'No Channel';
801
- }
802
- } else {
803
- console.log('โš ๏ธ Failed to fetch YouTube channel info:', channelResponse.status);
804
- channelName = userInfo.data?.user?.name || userInfo.data?.user?.email || 'Unknown Channel';
805
- }
806
- } catch (channelError) {
807
- console.log('โš ๏ธ Error fetching YouTube channel info:', channelError);
808
- channelName = userInfo.data?.user?.name || userInfo.data?.user?.email || 'Unknown Channel';
809
- }
810
-
811
- // Get stored authentication info to link YouTube data to user account
812
- let authToken = await AsyncStorage.getItem('onairos_jwt_token') || await AsyncStorage.getItem('enoch_token') || await AsyncStorage.getItem('auth_token');
813
- const storedUsername = await AsyncStorage.getItem('onairos_username');
814
- const finalUsername = storedUsername || username || userInfo.data?.user?.email || 'youtube_user';
815
-
816
- // If no auth token exists, create one now to ensure YouTube data is linked to user account
817
- if (!authToken || authToken.trim().length < 20) {
818
- console.log('๐Ÿ” No valid authentication token found, creating one for YouTube authentication...');
819
-
820
- try {
821
- // Create user accounts and get proper Enoch token
822
- const fallbackEmail = userInfo.data?.user?.email || `${finalUsername}@youtube.temp`;
823
-
824
- // Step 1: Create Enoch user first
825
- console.log('๐Ÿ” Step 1: Creating Enoch user for YouTube auth...');
826
- try {
827
- const enochRegisterResponse = await fetch('https://api2.onairos.uk/enoch/users/register', {
828
- method: 'POST',
829
- headers: {
830
- 'Content-Type': 'application/json'
831
- },
832
- body: JSON.stringify({
833
- email: fallbackEmail,
834
- name: finalUsername,
835
- photoUrl: userInfo.data?.user?.photo || ''
836
- })
837
- });
838
-
839
- console.log('๐Ÿ“ก Enoch register response status:', enochRegisterResponse.status);
840
- const enochResponseData = await enochRegisterResponse.json();
841
- console.log('๐Ÿ”— Enoch user creation response:', enochResponseData);
842
- } catch (enochError) {
843
- console.warn('โš ๏ธ Enoch user creation failed (continuing):', enochError);
844
- }
845
-
846
- // Step 2: Create Onairos account to get JWT token
847
- console.log('๐Ÿ” Step 2: Creating Onairos account for YouTube auth...');
848
- const onairosSignupResponse = await fetch('https://api2.onairos.uk/register/enoch', {
849
- method: 'POST',
850
- headers: {
851
- 'Content-Type': 'application/json'
852
- },
853
- body: JSON.stringify({
854
- email: fallbackEmail,
855
- username: finalUsername,
856
- name: finalUsername
857
- })
858
- });
859
-
860
- console.log('๐Ÿ“ก Onairos register response status:', onairosSignupResponse.status);
861
-
862
- if (onairosSignupResponse.ok) {
863
- const onairosResponseData = await onairosSignupResponse.json();
864
- console.log('๐Ÿ”— Onairos account creation response:', onairosResponseData);
865
-
866
- // Extract the token from the response
867
- if (onairosResponseData.token) {
868
- authToken = onairosResponseData.token;
869
- } else if (onairosResponseData.data?.token) {
870
- authToken = onairosResponseData.data.token;
871
- } else if (onairosResponseData.jwt) {
872
- authToken = onairosResponseData.jwt;
873
- }
874
-
875
- if (authToken) {
876
- // Store the Enoch token in all the standard locations
877
- await AsyncStorage.setItem('onairos_jwt_token', authToken);
878
- await AsyncStorage.setItem('enoch_token', authToken);
879
- await AsyncStorage.setItem('auth_token', authToken);
880
- await AsyncStorage.setItem('onairos_username', onairosResponseData.username || finalUsername);
881
-
882
- console.log('โœ… Successfully created and stored Enoch authentication token for YouTube');
883
- console.log('๐Ÿ”‘ Enoch token preview:', `${authToken.substring(0, 20)}...`);
884
- }
885
- } else {
886
- const errorText = await onairosSignupResponse.text();
887
- console.warn('โš ๏ธ Could not create Enoch auth token for YouTube:', errorText);
888
- }
889
- } catch (tokenError) {
890
- console.warn('โš ๏ธ Error creating Enoch auth token for YouTube:', tokenError);
891
- // Continue without token - backend will handle gracefully
892
- }
893
- } else {
894
- console.log('โœ… Found existing authentication token for YouTube auth');
895
- console.log('๐Ÿ”‘ Token preview:', `${authToken.substring(0, 20)}...`);
896
- }
897
-
898
- console.log('๐Ÿ”— Linking YouTube data to user:', finalUsername);
899
- console.log('๐Ÿ”‘ Using auth token for linking:', authToken ? `${authToken.substring(0, 20)}...` : 'No token');
900
- console.log('๐Ÿ“บ YouTube channel name:', channelName);
901
-
902
- // โœ… CRITICAL: Enhanced payload with comprehensive refresh token data
903
- const backendPayload = {
904
- session: {
905
- username: finalUsername,
906
- platform: 'youtube',
907
- timestamp: new Date().toISOString(),
908
- channelName: channelName,
909
- channelId: channelId
910
- },
911
- googleUser: userInfo.data?.user,
912
- accessToken: tokens.accessToken,
913
- idToken: tokens.idToken,
914
- refreshToken: refreshToken, // โœ… CRITICAL: Include refresh token
915
- serverAuthCode: refreshToken, // โœ… Alternative refresh mechanism (same as refreshToken)
916
-
917
- // โœ… CRITICAL: Additional compatibility fields for backend
918
- refresh_token: refreshToken, // Snake case version
919
- server_auth_code: refreshToken, // Snake case version
920
- authCode: refreshToken, // Alternative naming
921
-
922
- // Include user account linking information
923
- userAccountInfo: {
924
- username: finalUsername,
925
- email: userInfo.data?.user?.email,
926
- authToken: authToken,
927
- channelName: channelName,
928
- channelId: channelId,
929
- // CRITICAL: Include user identifier that matches your database
930
- userIdentifier: authToken ? `user-${authToken.substring(0, 10)}` : `youtube-${userInfo.data?.user?.email}`,
931
- googleId: userInfo.data?.user?.id,
932
- appleUserId: authToken?.includes('apple') ? authToken.split('.')[1] : null,
933
- // โœ… CRITICAL: Also include refresh token in userAccountInfo
934
- refreshToken: refreshToken,
935
- serverAuthCode: refreshToken
936
- },
937
- // Token expiry information
938
- tokenExpiry: new Date(Date.now() + 3600 * 1000).toISOString(), // 1 hour from now
939
- // Force refresh token request
940
- requestRefreshToken: true,
941
- // โœ… CRITICAL: Debug information for backend
942
- debugInfo: {
943
- hasRefreshToken: !!refreshToken,
944
- refreshTokenType: refreshToken ?
945
- (refreshToken.startsWith('4/') ? 'serverAuthCode' : 'refreshToken') : 'none',
946
- configuredForRefresh: true,
947
- forcedConsent: true,
948
- refreshTokenValue: refreshToken // Include actual value for debugging
949
- }
950
- };
951
-
952
- console.log('๐Ÿ“ค BACKEND PAYLOAD SUMMARY:');
953
- console.log('- hasAccessToken:', !!backendPayload.accessToken);
954
- console.log('- hasRefreshToken:', !!backendPayload.refreshToken);
955
- console.log('- hasServerAuthCode:', !!backendPayload.serverAuthCode);
956
- console.log('- refreshTokenType:', backendPayload.debugInfo.refreshTokenType);
957
- console.log('- userEmail:', userInfo.data?.user?.email);
958
- console.log('- channelName:', channelName);
959
-
960
- console.log('๐Ÿ“‹ COMPLETE BACKEND PAYLOAD:');
961
- console.log(JSON.stringify(backendPayload, null, 2));
962
-
963
- // Send the tokens to your backend for YouTube data processing with ENHANCED LOGGING
964
- console.log('๐Ÿ“ค Sending YouTube auth to backend with refresh token:', !!refreshToken);
965
-
966
- const backendResponse = await fetch('https://api2.onairos.uk/youtube/native-auth', {
967
- method: 'POST',
968
- headers: {
969
- 'Content-Type': 'application/json',
970
- ...(authToken && { 'Authorization': authToken }) // Include auth token if available
971
- },
972
- body: JSON.stringify(backendPayload)
973
- });
974
-
975
- console.log('๐Ÿ“ก Backend response status:', backendResponse.status);
976
- console.log('๐Ÿ“ก Backend response headers:', backendResponse.headers);
977
-
978
- if (backendResponse.ok) {
979
- const responseData = await backendResponse.json();
980
- console.log('โœ… YouTube connection successful');
981
- console.log('๐Ÿ“‹ COMPLETE BACKEND RESPONSE:');
982
- console.log(JSON.stringify(responseData, null, 2));
983
-
984
- // โœ… Enhanced verification with temporary mode detection (exact backend fields)
985
- const isTemporaryMode = responseData.validation?.isTemporaryMode === true ||
986
- responseData.temporaryMode?.enabled === true ||
987
- responseData.isTemporaryMode === true ||
988
- (responseData.message && responseData.message.includes('temporary access token mode'));
989
-
990
- if (isTemporaryMode) {
991
- console.log('๐Ÿ”„ [YOUTUBE AUTH] YouTube connected in temporary mode');
992
- console.log('โœ… [YOUTUBE AUTH] Training will work, but connection expires in ~1 hour');
993
- console.log('โ„น๏ธ [YOUTUBE AUTH] User can reconnect later for refresh tokens if needed');
994
- } else if (responseData.hasRefreshToken || responseData.refreshTokenReceived) {
995
- console.log('โœ… [YOUTUBE AUTH] Backend confirmed refresh token received');
996
- console.log('โœ… [YOUTUBE AUTH] Full YouTube connection with persistent access');
997
- } else {
998
- console.warn('โš ๏ธ [YOUTUBE AUTH] Backend did not confirm refresh token');
999
- console.warn('๐Ÿ” [YOUTUBE AUTH] Response data keys:', Object.keys(responseData));
1000
- console.warn('โš ๏ธ [YOUTUBE AUTH] Connection may fail when tokens expire');
1001
- }
1002
-
1003
- return true;
1004
- } else {
1005
- const errorData = await backendResponse.text();
1006
- console.error('โŒ YouTube auth failed:', backendResponse.status);
1007
- console.error('๐Ÿ“‹ BACKEND ERROR RESPONSE:');
1008
- console.error(errorData);
1009
- return false;
1010
- }
1011
-
1012
- } catch (error: any) {
1013
- console.error('โŒ Google Sign-In error:', error);
1014
-
1015
- if (error.code === statusCodes.SIGN_IN_CANCELLED) {
1016
- console.log('User cancelled Google Sign-In');
1017
- } else if (error.code === statusCodes.IN_PROGRESS) {
1018
- console.log('Google Sign-In already in progress');
1019
- } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
1020
- console.log('Google Play Services not available');
1021
- }
1022
-
1023
- return false;
1024
- }
1025
- }
1026
-
1027
- // Instagram is commented out in the UI, but keeping the code for future use
1028
- if (platform === 'instagram') {
1029
- // Simulate Facebook Login SDK for Instagram
1030
- console.log('Initiating Facebook Login for Instagram');
1031
- return new Promise(resolve => {
1032
- setTimeout(() => {
1033
- console.log('Facebook Login completed successfully');
1034
- resolve(true);
1035
- }, 1000);
1036
- });
1037
- }
1038
-
1039
- return false;
1040
- };
1041
-
1042
- /**
1043
- * Check if a URL is an OAuth callback
1044
- */
1045
- export const isOAuthCallback = (url: string): boolean => {
1046
- return url.includes('auth/callback') || url.includes('code=');
1047
- };
1048
-
1049
- /**
1050
- * Exchange authorization code for access token
1051
- * This would typically be done on a server, but we're simulating it here
1052
- */
1053
- export const exchangeCodeForToken = async (code: string, platform: string): Promise<any> => {
1054
- console.log(`Exchanging code for token for platform: ${platform}`);
1055
-
1056
- try {
1057
- // Use the proxy server to exchange the code for a token
1058
- const tokenUrl = `https://api2.onairos.uk/${platform}/token`;
1059
-
1060
- // Make a POST request to the proxy
1061
- const response = await fetch(tokenUrl, {
1062
- method: 'POST',
1063
- headers: {
1064
- 'Content-Type': 'application/json'
1065
- },
1066
- body: JSON.stringify({
1067
- code: code,
1068
- platform: platform
1069
- })
1070
- });
1071
-
1072
- if (!response.ok) {
1073
- console.error(`Error exchanging code for token: ${response.status}`);
1074
- throw new Error(`Token exchange failed with status ${response.status}`);
1075
- }
1076
-
1077
- const data = await response.json();
1078
- console.log(`Token exchange successful for ${platform}`);
1079
- return data;
1080
- } catch (error) {
1081
- console.error(`Error exchanging code for token:`, error);
1082
-
1083
- // Fallback to simulation if the API call fails
1084
- console.log('Falling back to simulated token response');
1085
- return {
1086
- access_token: `${platform}_access_token_${Math.random().toString(36).substring(7)}`,
1087
- refresh_token: `${platform}_refresh_token_${Math.random().toString(36).substring(7)}`,
1088
- expires_in: 3600,
1089
- };
1090
- }
1091
- };
1092
-
1093
- /**
1094
- * Refresh YouTube tokens when they expire
1095
- * This should be called when the backend reports token expiry
1096
- */
1097
- export const refreshYouTubeTokens = async (): Promise<boolean> => {
1098
- try {
1099
- console.log('๐Ÿ”„ Refreshing YouTube tokens...');
1100
-
1101
- // Get fresh tokens from Google SDK
1102
- const freshTokens = await GoogleSignin.getTokens();
1103
- if (!freshTokens) {
1104
- console.error('โŒ Failed to get fresh tokens from Google SDK');
1105
- return false;
1106
- }
1107
-
1108
- // Get current user info
1109
- const currentUser = await GoogleSignin.getCurrentUser();
1110
- if (!currentUser) {
1111
- console.error('โŒ No current Google user found');
1112
- return false;
1113
- }
1114
-
1115
- // Get stored auth token
1116
- const authToken = await AsyncStorage.getItem('onairos_jwt_token') ||
1117
- await AsyncStorage.getItem('enoch_token') ||
1118
- await AsyncStorage.getItem('auth_token');
1119
-
1120
- if (!authToken) {
1121
- console.error('โŒ No auth token found for YouTube refresh');
1122
- return false;
1123
- }
1124
-
1125
- // Send refreshed tokens to backend
1126
- const refreshResponse = await fetch('https://api2.onairos.uk/youtube/refresh-token', {
1127
- method: 'POST',
1128
- headers: {
1129
- 'Content-Type': 'application/json',
1130
- 'Authorization': authToken
1131
- },
1132
- body: JSON.stringify({
1133
- accessToken: freshTokens.accessToken,
1134
- idToken: freshTokens.idToken,
1135
- refreshToken: currentUser.serverAuthCode,
1136
- userEmail: currentUser.user?.email,
1137
- tokenExpiry: new Date(Date.now() + 3600 * 1000).toISOString(), // 1 hour from now
1138
- timestamp: new Date().toISOString()
1139
- })
1140
- });
1141
-
1142
- if (refreshResponse.ok) {
1143
- const responseData = await refreshResponse.json();
1144
- console.log('โœ… YouTube tokens refreshed successfully:', responseData);
1145
- return true;
1146
- } else {
1147
- const errorData = await refreshResponse.text();
1148
- console.error('โŒ YouTube token refresh failed:', refreshResponse.status, errorData);
1149
- return false;
1150
- }
1151
- } catch (error) {
1152
- console.error('โŒ Error refreshing YouTube tokens:', error);
1153
- return false;
1154
- }
1155
- };
1156
-
1157
- /**
1158
- * Trigger training restart after YouTube re-authentication
1159
- * This signals the backend to restart training with the new refresh token
1160
- */
1161
- const triggerTrainingRestart = async (username: string, authToken: string): Promise<void> => {
1162
- try {
1163
- console.log('๐Ÿ”„ [TRAINING RESTART] Triggering training restart for user:', username);
1164
-
1165
- const response = await fetch('https://api2.onairos.uk/mobile-training/restart', {
1166
- method: 'POST',
1167
- headers: {
1168
- 'Content-Type': 'application/json',
1169
- 'Authorization': authToken
1170
- },
1171
- body: JSON.stringify({
1172
- username: username,
1173
- reason: 'youtube_reauth',
1174
- platform: 'youtube',
1175
- timestamp: new Date().toISOString(),
1176
- requestNewTraining: true
1177
- })
1178
- });
1179
-
1180
- if (response.ok) {
1181
- const responseData = await response.json();
1182
- console.log('โœ… [TRAINING RESTART] Training restart successful:', responseData);
1183
- } else {
1184
- const errorData = await response.text();
1185
- console.error('โŒ [TRAINING RESTART] Training restart failed:', response.status, errorData);
1186
- throw new Error(`Training restart failed: ${response.status}`);
1187
- }
1188
- } catch (error) {
1189
- console.error('โŒ [TRAINING RESTART] Error triggering training restart:', error);
1190
- throw error;
1191
- }
1192
- };
1193
-
1194
- /**
1195
- * Test function to verify YouTube refresh token functionality
1196
- * Call this in your app to test the YouTube connection
1197
- */
1198
- export const testYouTubeRefreshToken = async (username: string): Promise<void> => {
1199
- console.log('๐Ÿงช Testing YouTube refresh token functionality...');
1200
- console.log('๐Ÿ‘ค User:', username);
1201
-
1202
- try {
1203
- // Test the debug function first
1204
- const debugInfo = await debugYouTubeTokens();
1205
- console.log('๐Ÿ” Current token status:', debugInfo);
1206
-
1207
- if (!debugInfo.hasRefreshToken) {
1208
- console.log('โš ๏ธ No refresh token found - attempting to fix...');
1209
- const success = await fixUserYouTubeConnection(username);
1210
-
1211
- if (success) {
1212
- console.log('โœ… YouTube connection fixed! Testing again...');
1213
- const newDebugInfo = await debugYouTubeTokens();
1214
- console.log('๐Ÿ” New token status:', newDebugInfo);
1215
- } else {
1216
- console.error('โŒ Failed to fix YouTube connection');
1217
- }
1218
- } else {
1219
- console.log('โœ… Refresh token already available');
1220
- }
1221
-
1222
- } catch (error) {
1223
- console.error('โŒ Error testing YouTube refresh token:', error);
1224
- }
1225
- };
1226
-
1227
- /**
1228
- * Request email verification code
1229
- */
1230
- export const requestEmailVerification = async (email: string, testMode: boolean = false): Promise<any> => {
1231
- try {
1232
- console.log('๐Ÿ“ง Requesting email verification for:', email);
1233
-
1234
- const response = await fetch(`${API_CONFIG.BASE_URL}/email/verification`, {
1235
- method: 'POST',
1236
- headers: getApiHeaders(),
1237
- body: JSON.stringify({
1238
- email,
1239
- action: 'request',
1240
- testMode
1241
- }),
1242
- });
1243
-
1244
- const result = await response.json();
1245
-
1246
- if (response.ok) {
1247
- return {
1248
- success: true,
1249
- message: result.message || 'Verification code sent to your email'
1250
- };
1251
- } else {
1252
- return {
1253
- success: false,
1254
- error: result.message || 'Failed to send verification code'
1255
- };
1256
- }
1257
- } catch (error) {
1258
- console.error('โŒ Error requesting email verification:', error);
1259
- return {
1260
- success: false,
1261
- error: 'Network error. Please check your connection and try again.'
1262
- };
1263
- }
1264
- };
1265
-
1266
- /**
1267
- * Verify email code
1268
- */
1269
- export const verifyEmailCode = async (email: string, code: string, testMode: boolean = false): Promise<any> => {
1270
- try {
1271
- console.log('๐Ÿ” Verifying email code for:', email);
1272
-
1273
- const response = await fetch(`${API_CONFIG.BASE_URL}/email/verification`, {
1274
- method: 'POST',
1275
- headers: getApiHeaders(),
1276
- body: JSON.stringify({
1277
- email,
1278
- code,
1279
- action: 'verify',
1280
- testMode
1281
- }),
1282
- });
1283
-
1284
- const result = await response.json();
1285
-
1286
- if (response.ok) {
1287
- return {
1288
- success: true,
1289
- message: result.message || 'Email verified successfully',
1290
- existingUser: result.existingUser || false,
1291
- token: result.token
1292
- };
1293
- } else {
1294
- return {
1295
- success: false,
1296
- error: result.message || 'Invalid verification code'
1297
- };
1298
- }
1299
- } catch (error) {
1300
- console.error('โŒ Error verifying email code:', error);
1301
- return {
1302
- success: false,
1303
- error: 'Network error. Please check your connection and try again.'
1304
- };
1305
- }
1306
- };
1307
-
1308
- /**
1309
- * Check email verification status
1310
- */
1311
- export const checkEmailVerificationStatus = async (email: string, testMode: boolean = false): Promise<any> => {
1312
- try {
1313
- const response = await fetch(`${API_CONFIG.BASE_URL}/email/verification/status`, {
1314
- method: 'POST',
1315
- headers: getApiHeaders(),
1316
- body: JSON.stringify({
1317
- email,
1318
- testMode
1319
- }),
1320
- });
1321
-
1322
- const result = await response.json();
1323
-
1324
- return {
1325
- success: response.ok,
1326
- isPending: result.isPending || false,
1327
- message: result.message
1328
- };
1329
- } catch (error) {
1330
- console.error('โŒ Error checking email verification status:', error);
1331
- return {
1332
- success: false,
1333
- isPending: false,
1334
- error: 'Network error'
1335
- };
1336
- }
1337
- };
1338
-
1339
- /**
1340
- * Initialize platform auth service
1341
- */
1342
- export const initializePlatformAuthService = () => {
1343
- console.log('๐Ÿ”ง Platform auth service initialized');
1344
- // Initialize Google Sign-In
1345
- initializeGoogleSignIn();
1346
- };
1
+ import { Platform, Linking } from 'react-native';
2
+ import AsyncStorage from '@react-native-async-storage/async-storage';
3
+ import type { PlatformAuthConfig } from '../types';
4
+ import { makeDeveloperRequest, getApiConfig, storeJWT, extractUsernameFromJWT } from './apiKeyService';
5
+
6
+ // ๐Ÿ”‘ CRITICAL: Use two-tier authentication system
7
+ // - Developer API key for email verification requests
8
+ // - JWT tokens for user-authenticated requests after email verification
9
+
10
+ /**
11
+ * Initialize the platform auth service
12
+ * This service now uses the two-tier authentication system
13
+ */
14
+ export const initializePlatformAuthService = async (): Promise<void> => {
15
+ try {
16
+ // Check if app is already initialized with API key
17
+ const existingConfig = getApiConfig();
18
+
19
+ if (existingConfig && existingConfig.apiKey) {
20
+ console.log('๐Ÿ”‘ Platform auth service using existing app configuration');
21
+ console.log(`โœ… Environment: ${existingConfig.environment}`);
22
+ return;
23
+ }
24
+
25
+ // If no app initialization, we can't proceed
26
+ console.error('โŒ Platform auth service requires app-level API key initialization');
27
+ throw new Error('Platform auth service requires app-level API key initialization. Please call initializeApiKey() first.');
28
+ } catch (error) {
29
+ console.error('โŒ Failed to initialize platform auth service:', error);
30
+ throw error;
31
+ }
32
+ };
33
+
34
+ // Configuration for each platform's authentication
35
+ let PLATFORM_AUTH_CONFIG: Record<string, PlatformAuthConfig> = {
36
+ instagram: {
37
+ hasNativeSDK: false, // Instagram uses OAuth WebView flow
38
+ authEndpoint: '/instagram/authorize',
39
+ color: '#E1306C',
40
+ },
41
+ youtube: {
42
+ hasNativeSDK: true, // Native Google Sign-In SDK enabled
43
+ nativeSDKPackage: '@react-native-google-signin/google-signin',
44
+ authEndpoint: '/youtube/authorize',
45
+ color: '#FF0000',
46
+ clientId: '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com',
47
+ redirectUri: 'onairosevents://auth/callback',
48
+ scope: 'https://www.googleapis.com/auth/youtube.readonly',
49
+ responseType: 'code',
50
+ },
51
+ reddit: {
52
+ hasNativeSDK: false,
53
+ authEndpoint: '/reddit/authorize',
54
+ color: '#FF4500',
55
+ },
56
+ pinterest: {
57
+ hasNativeSDK: false,
58
+ authEndpoint: '/pinterest/authorize',
59
+ color: '#E60023',
60
+ },
61
+ email: {
62
+ hasNativeSDK: false,
63
+ authEndpoint: '/gmail/authorize',
64
+ color: '#4285F4',
65
+ },
66
+ };
67
+
68
+ /**
69
+ * Checks if a native SDK is available for the given platform
70
+ */
71
+ export const hasNativeSDK = (platform: string): boolean => {
72
+ const config = PLATFORM_AUTH_CONFIG[platform];
73
+ return config?.hasNativeSDK || false;
74
+ };
75
+
76
+ /**
77
+ * Gets the auth endpoint URL for a platform
78
+ */
79
+ export const getAuthEndpoint = (platform: string): string => {
80
+ const config = PLATFORM_AUTH_CONFIG[platform];
81
+ return config?.authEndpoint || '';
82
+ };
83
+
84
+ /**
85
+ * Gets the color associated with a platform
86
+ */
87
+ export const getPlatformColor = (platform: string): string => {
88
+ const config = PLATFORM_AUTH_CONFIG[platform];
89
+ return config?.color || '#000000';
90
+ };
91
+
92
+ /**
93
+ * Initiates the OAuth flow for a platform
94
+ * @param platform The platform to authenticate with
95
+ * @param username The username to associate with the authentication
96
+ * @param appName The app name to use for the OAuth session (optional)
97
+ * @returns A Promise that resolves to the OAuth URL to open in a WebView or null if using native SDK
98
+ */
99
+ export const initiateOAuth = async (platform: string, username: string, appName?: string): Promise<string | null> => {
100
+ try {
101
+ console.log('๐Ÿš€ Initiating OAuth for platform:', platform);
102
+ console.log('๐Ÿ‘ค Username:', username);
103
+ console.log('๐Ÿ“ฑ App name:', appName);
104
+
105
+ // Check if the platform is supported
106
+ if (!PLATFORM_AUTH_CONFIG[platform]) {
107
+ console.error('โŒ Unsupported platform:', platform);
108
+ throw new Error(`Unsupported platform: ${platform}`);
109
+ }
110
+
111
+ // Check if platform has a native SDK
112
+ if (PLATFORM_AUTH_CONFIG[platform].hasNativeSDK) {
113
+ console.log('๐Ÿ“ฑ Platform uses native SDK, returning null');
114
+ // Return null to indicate that we should use the native SDK
115
+ return null;
116
+ }
117
+
118
+ console.log('๐ŸŒ Platform uses OAuth WebView flow');
119
+ console.log('๐Ÿ”— Auth endpoint:', PLATFORM_AUTH_CONFIG[platform].authEndpoint);
120
+
121
+ // Pre-flight connectivity check
122
+ console.log('๐Ÿ” Performing pre-flight connectivity check...');
123
+ const connectivityResult = await testApiConnectivity();
124
+
125
+ if (!connectivityResult.success) {
126
+ console.error('โŒ Pre-flight connectivity check failed:', connectivityResult.error);
127
+ throw new Error(`Cannot reach authentication server: ${connectivityResult.error}`);
128
+ }
129
+
130
+ console.log('โœ… Pre-flight connectivity check passed');
131
+
132
+ // Handle Instagram with specific API format
133
+ if (platform === 'instagram') {
134
+ const state = 'djksbfds';
135
+ const jsonData = {
136
+ session: {
137
+ oauthState: state,
138
+ username: username || 'Avatar',
139
+ },
140
+ };
141
+
142
+ console.log('๐Ÿ“ค Sending Instagram OAuth request:', jsonData);
143
+
144
+ const response = await makeDeveloperRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
145
+ method: 'POST',
146
+ body: JSON.stringify(jsonData),
147
+ });
148
+
149
+ console.log('๐Ÿ“ก Instagram OAuth response status:', response.status);
150
+
151
+ if (!response.ok) {
152
+ const errorText = await response.text();
153
+ console.error('โŒ Instagram OAuth API error:', errorText);
154
+ throw new Error(`Instagram OAuth API error: ${response.status} - ${errorText}`);
155
+ }
156
+
157
+ const responseData = await response.json();
158
+ console.log('๐Ÿ“ฅ Instagram OAuth response data:', responseData);
159
+
160
+ if (responseData.instagramURL) {
161
+ console.log('โœ… Instagram OAuth URL received:', responseData.instagramURL);
162
+
163
+ // Validate the URL before returning
164
+ if (await validateOAuthUrl(responseData.instagramURL)) {
165
+ return responseData.instagramURL;
166
+ } else {
167
+ throw new Error('Received invalid Instagram OAuth URL');
168
+ }
169
+ }
170
+
171
+ console.error('โŒ No Instagram URL found in response');
172
+ throw new Error('No Instagram URL found in response');
173
+ }
174
+
175
+ // Prepare the request body for other platforms
176
+ const jsonData = {
177
+ session: {
178
+ oauthState: 'djksbfds', // Use same state for all platforms
179
+ username: username || 'Avatar',
180
+ appName: appName || 'DefaultApp',
181
+ },
182
+ };
183
+
184
+ console.log(`๐Ÿ“ค Sending ${platform} OAuth request:`, jsonData);
185
+
186
+ // Make the authenticated request to get the OAuth URL
187
+ const response = await makeDeveloperRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
188
+ method: 'POST',
189
+ body: JSON.stringify(jsonData),
190
+ });
191
+
192
+ console.log(`๐Ÿ“ก ${platform} OAuth response status:`, response.status);
193
+
194
+ if (!response.ok) {
195
+ const errorText = await response.text();
196
+ console.error(`โŒ ${platform} OAuth API error:`, errorText);
197
+ throw new Error(`${platform} OAuth API error: ${response.status} - ${errorText}`);
198
+ }
199
+
200
+ // Parse the response
201
+ const data = await response.json();
202
+ console.log(`๐Ÿ“ฅ ${platform} OAuth response data:`, data);
203
+
204
+ // Extra logging for Gmail to help debug
205
+ if (platform === 'email') {
206
+ console.log('๐Ÿ” Gmail OAuth response keys:', Object.keys(data));
207
+ console.log('๐Ÿ” Gmail OAuth full response:', JSON.stringify(data, null, 2));
208
+ }
209
+
210
+ // Check if the response contains the OAuth URL based on platform
211
+ let oauthUrl: string | null = null;
212
+
213
+ switch (platform) {
214
+ case 'reddit':
215
+ oauthUrl = data.redditURL;
216
+ break;
217
+ case 'pinterest':
218
+ oauthUrl = data.pinterestURL;
219
+ break;
220
+ case 'youtube':
221
+ oauthUrl = data.youtubeURL;
222
+ break;
223
+ case 'email':
224
+ // Gmail might return under different field names
225
+ oauthUrl = data.emailURL || data.gmailURL || data.authUrl || data.url;
226
+ break;
227
+ default:
228
+ oauthUrl = data.url;
229
+ break;
230
+ }
231
+
232
+ if (!oauthUrl) {
233
+ console.error(`โŒ No OAuth URL found in response for ${platform}. Response:`, data);
234
+ throw new Error(`No OAuth URL found in response for ${platform}`);
235
+ }
236
+
237
+ console.log(`โœ… ${platform} OAuth URL received:`, oauthUrl);
238
+
239
+ // Validate the URL before returning
240
+ if (await validateOAuthUrl(oauthUrl)) {
241
+ return oauthUrl;
242
+ } else {
243
+ throw new Error(`Received invalid ${platform} OAuth URL`);
244
+ }
245
+ } catch (error) {
246
+ console.error(`Error initiating OAuth for ${platform}:`, error);
247
+ throw error;
248
+ }
249
+ };
250
+
251
+ /**
252
+ * Validates an OAuth URL to ensure it's reachable
253
+ * @param url The OAuth URL to validate
254
+ * @returns Promise<boolean> indicating if the URL is valid and reachable
255
+ */
256
+ const validateOAuthUrl = async (url: string): Promise<boolean> => {
257
+ try {
258
+ console.log('๐Ÿ” Validating OAuth URL:', url);
259
+
260
+ // Basic URL format validation
261
+ if (!url || typeof url !== 'string') {
262
+ console.error('โŒ Invalid URL format:', url);
263
+ return false;
264
+ }
265
+
266
+ // Check if URL starts with https
267
+ if (!url.startsWith('https://')) {
268
+ console.error('โŒ URL must use HTTPS:', url);
269
+ return false;
270
+ }
271
+
272
+ // Try to parse the URL
273
+ try {
274
+ new URL(url);
275
+ } catch (parseError) {
276
+ console.error('โŒ URL parsing failed:', parseError);
277
+ return false;
278
+ }
279
+
280
+ // Make a HEAD request to check if the URL is reachable
281
+ const controller = new AbortController();
282
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
283
+
284
+ try {
285
+ const response = await fetch(url, {
286
+ method: 'HEAD',
287
+ signal: controller.signal,
288
+ });
289
+
290
+ clearTimeout(timeoutId);
291
+
292
+ // Accept any response that's not a network error
293
+ // OAuth pages might return various status codes
294
+ console.log('โœ… OAuth URL validation successful, status:', response.status);
295
+ return true;
296
+ } catch (fetchError) {
297
+ clearTimeout(timeoutId);
298
+
299
+ if (fetchError.name === 'AbortError') {
300
+ console.warn('โš ๏ธ OAuth URL validation timeout, but proceeding anyway');
301
+ return true; // Allow timeout as URLs might be slow to respond
302
+ }
303
+
304
+ console.warn('โš ๏ธ OAuth URL validation failed, but proceeding anyway:', fetchError.message);
305
+ return true; // Allow network errors as they might be temporary
306
+ }
307
+ } catch (error) {
308
+ console.warn('โš ๏ธ OAuth URL validation error, but proceeding anyway:', error);
309
+ return true; // Allow validation errors to not block the flow
310
+ }
311
+ };
312
+
313
+ /**
314
+ * Initiates the native SDK authentication flow for a platform
315
+ * @param platform The platform to authenticate with
316
+ * @returns A Promise that resolves to the authentication result
317
+ */
318
+ export const initiateNativeAuth = async (platform: string, username?: string): Promise<boolean> => {
319
+ if (platform === 'youtube') {
320
+ console.log('๐Ÿ”— Initiating native Google Sign-In for YouTube');
321
+ try {
322
+ // Check if Google Sign-In package is available
323
+ let GoogleSignin, statusCodes;
324
+ try {
325
+ const googleSignInModule = require('@react-native-google-signin/google-signin');
326
+ GoogleSignin = googleSignInModule.GoogleSignin;
327
+ statusCodes = googleSignInModule.statusCodes;
328
+ } catch (importError) {
329
+ console.error('โŒ Google Sign-In package not available:', importError);
330
+ throw new Error('Google Sign-In SDK not installed. Please install @react-native-google-signin/google-signin');
331
+ }
332
+
333
+ // Configure Google Sign-In with better error handling
334
+ try {
335
+ const youtubeConfig = PLATFORM_AUTH_CONFIG.youtube;
336
+ const webClientId = youtubeConfig.clientId || '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com';
337
+ const iosClientId = youtubeConfig.iosClientId || webClientId;
338
+
339
+ await GoogleSignin.configure({
340
+ webClientId: webClientId,
341
+ iosClientId: iosClientId,
342
+ scopes: ['https://www.googleapis.com/auth/youtube.readonly'],
343
+ offlineAccess: true,
344
+ hostedDomain: '',
345
+ forceCodeForRefreshToken: true,
346
+ accountName: '',
347
+ });
348
+ console.log('โœ… Google Sign-In configured successfully with client ID:', webClientId.substring(0, 20) + '...');
349
+ } catch (configError) {
350
+ console.error('โŒ Google Sign-In configuration failed:', configError);
351
+ throw new Error(`Google Sign-In configuration failed: ${configError.message || configError}`);
352
+ }
353
+
354
+ // Check if Google Play Services are available (Android only)
355
+ try {
356
+ await GoogleSignin.hasPlayServices({ showPlayServicesUpdateDialog: true });
357
+ console.log('โœ… Google Play Services available');
358
+ } catch (playServicesError) {
359
+ console.error('โŒ Google Play Services error:', playServicesError);
360
+ throw new Error(`Google Play Services not available: ${playServicesError.message || playServicesError}`);
361
+ }
362
+
363
+ // Sign in with Google
364
+ let userInfo;
365
+ try {
366
+ userInfo = await GoogleSignin.signIn();
367
+ console.log('โœ… Google Sign-In successful:', userInfo.user?.email);
368
+ } catch (signInError) {
369
+ console.error('โŒ Google Sign-In failed:', signInError);
370
+
371
+ // Handle specific error codes
372
+ if (signInError.code === statusCodes.SIGN_IN_CANCELLED) {
373
+ throw new Error('Google Sign-In was cancelled by user');
374
+ } else if (signInError.code === statusCodes.IN_PROGRESS) {
375
+ throw new Error('Google Sign-In already in progress');
376
+ } else if (signInError.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
377
+ throw new Error('Google Play Services not available or outdated');
378
+ } else {
379
+ throw new Error(`Google Sign-In failed: ${signInError.message || signInError}`);
380
+ }
381
+ }
382
+
383
+ // Get access token for API calls
384
+ const tokens = await GoogleSignin.getTokens();
385
+ console.log('๐Ÿ”‘ Got Google tokens');
386
+
387
+ // Get current user info with refresh token
388
+ const currentUser = await GoogleSignin.getCurrentUser();
389
+ console.log('๐Ÿ‘ค Current user info:', currentUser?.user?.email);
390
+
391
+ // Extract refresh token from server auth code
392
+ let refreshToken = null;
393
+ if (currentUser?.serverAuthCode) {
394
+ console.log('๐Ÿ”„ Server auth code available for refresh token');
395
+ refreshToken = currentUser.serverAuthCode;
396
+ }
397
+
398
+ if (!refreshToken) {
399
+ console.warn('โš ๏ธ No refresh token available - token refresh may fail later');
400
+ } else {
401
+ console.log('โœ… Refresh token available for YouTube connection');
402
+ }
403
+
404
+ // Fetch YouTube channel information
405
+ let channelName = 'Unknown Channel';
406
+ let channelId = null;
407
+ try {
408
+ console.log('๐Ÿ“บ Fetching YouTube channel information...');
409
+ const channelResponse = await fetch('https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true', {
410
+ headers: {
411
+ 'Authorization': `Bearer ${tokens.accessToken}`,
412
+ 'Accept': 'application/json'
413
+ }
414
+ });
415
+
416
+ if (channelResponse.ok) {
417
+ const channelData = await channelResponse.json();
418
+ if (channelData.items && channelData.items.length > 0) {
419
+ channelName = channelData.items[0].snippet.title;
420
+ channelId = channelData.items[0].id;
421
+ console.log('โœ… YouTube channel found:', channelName);
422
+ }
423
+ }
424
+ } catch (channelError) {
425
+ console.log('โš ๏ธ Error fetching YouTube channel info:', channelError);
426
+ channelName = userInfo.user?.name || userInfo.user?.email || 'Unknown Channel';
427
+ }
428
+
429
+ // Get authentication info
430
+ let authToken = await AsyncStorage.getItem('onairos_jwt_token') ||
431
+ await AsyncStorage.getItem('enoch_token') ||
432
+ await AsyncStorage.getItem('auth_token');
433
+ const storedUsername = await AsyncStorage.getItem('onairos_username');
434
+ const finalUsername = storedUsername || username || userInfo.user?.email || 'youtube_user';
435
+
436
+ // Create auth token if needed
437
+ if (!authToken || authToken.trim().length < 20) {
438
+ console.log('๐Ÿ” Creating authentication token for YouTube...');
439
+
440
+ try {
441
+ const fallbackEmail = userInfo.user?.email || `${finalUsername}@youtube.temp`;
442
+
443
+ // Create user accounts and get JWT token
444
+ const onairosSignupResponse = await fetch('https://api2.onairos.uk/register/enoch', {
445
+ method: 'POST',
446
+ headers: {
447
+ 'Content-Type': 'application/json'
448
+ },
449
+ body: JSON.stringify({
450
+ email: fallbackEmail,
451
+ username: finalUsername,
452
+ name: finalUsername
453
+ })
454
+ });
455
+
456
+ if (onairosSignupResponse.ok) {
457
+ const onairosResponseData = await onairosSignupResponse.json();
458
+
459
+ // Extract token from response
460
+ authToken = onairosResponseData.token || onairosResponseData.data?.token || onairosResponseData.jwt;
461
+
462
+ if (authToken) {
463
+ // Store tokens
464
+ await AsyncStorage.setItem('onairos_jwt_token', authToken);
465
+ await AsyncStorage.setItem('enoch_token', authToken);
466
+ await AsyncStorage.setItem('auth_token', authToken);
467
+ await AsyncStorage.setItem('onairos_username', onairosResponseData.username || finalUsername);
468
+
469
+ console.log('โœ… Successfully created and stored authentication token');
470
+ }
471
+ }
472
+ } catch (tokenError) {
473
+ console.warn('โš ๏ธ Error creating auth token:', tokenError);
474
+ }
475
+ }
476
+
477
+ console.log('๐Ÿ”— Linking YouTube data to user:', finalUsername);
478
+ console.log('๐Ÿ“บ YouTube channel name:', channelName);
479
+
480
+ // Send tokens to backend for YouTube data processing
481
+ const backendResponse = await fetch('https://api2.onairos.uk/youtube/native-auth', {
482
+ method: 'POST',
483
+ headers: {
484
+ 'Content-Type': 'application/json',
485
+ ...(authToken && { 'Authorization': `Bearer ${authToken}` })
486
+ },
487
+ body: JSON.stringify({
488
+ session: {
489
+ username: finalUsername,
490
+ platform: 'youtube',
491
+ timestamp: new Date().toISOString(),
492
+ channelName: channelName,
493
+ channelId: channelId
494
+ },
495
+ googleUser: userInfo.user,
496
+ accessToken: tokens.accessToken,
497
+ idToken: tokens.idToken,
498
+ refreshToken: refreshToken, // CRITICAL: Include refresh token
499
+ serverAuthCode: currentUser?.serverAuthCode,
500
+ userAccountInfo: {
501
+ username: finalUsername,
502
+ email: userInfo.user?.email,
503
+ authToken: authToken,
504
+ channelName: channelName,
505
+ channelId: channelId,
506
+ userIdentifier: authToken ? `user-${authToken.substring(0, 10)}` : `youtube-${userInfo.user?.email}`,
507
+ googleId: userInfo.user?.id,
508
+ },
509
+ tokenExpiry: new Date(Date.now() + 3600 * 1000).toISOString(), // 1 hour from now
510
+ requestRefreshToken: true
511
+ })
512
+ });
513
+
514
+ if (backendResponse.ok) {
515
+ const responseData = await backendResponse.json();
516
+ console.log('โœ… YouTube connection processed by backend:', responseData);
517
+ return true;
518
+ } else {
519
+ const errorData = await backendResponse.text();
520
+ console.error('โŒ Backend processing failed:', backendResponse.status, errorData);
521
+ return false;
522
+ }
523
+
524
+ } catch (error: any) {
525
+ console.error('โŒ Google Sign-In error:', error);
526
+
527
+ const { statusCodes: StatusCodes } = require('@react-native-google-signin/google-signin');
528
+
529
+ if (error.code === StatusCodes.SIGN_IN_CANCELLED) {
530
+ console.log('User cancelled Google Sign-In');
531
+ } else if (error.code === StatusCodes.IN_PROGRESS) {
532
+ console.log('Google Sign-In already in progress');
533
+ } else if (error.code === StatusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
534
+ console.log('Google Play Services not available');
535
+ }
536
+
537
+ return false;
538
+ }
539
+ }
540
+
541
+ return false;
542
+ };
543
+
544
+ /**
545
+ * Handles the OAuth callback
546
+ * @param url The callback URL
547
+ * @returns The authorization code extracted from the URL
548
+ */
549
+ export const handleOAuthCallback = (url: string): string | null => {
550
+ try {
551
+ // Parse the URL
552
+ const parsedUrl = new URL(url);
553
+
554
+ // Extract the authorization code
555
+ return parsedUrl.searchParams.get('code');
556
+ } catch (error) {
557
+ console.error('Error handling OAuth callback:', error);
558
+ return null;
559
+ }
560
+ };
561
+
562
+ /**
563
+ * Checks if a URL is an OAuth callback
564
+ * @param url The URL to check
565
+ * @returns True if the URL is an OAuth callback
566
+ */
567
+ export const isOAuthCallback = (url: string): boolean => {
568
+ // Check if the URL starts with our redirect URI
569
+ return url.startsWith('onairosanime://auth/');
570
+ };
571
+
572
+ /**
573
+ * Test connectivity to the Onairos API server
574
+ */
575
+ export const testApiConnectivity = async (): Promise<{ success: boolean; error?: string }> => {
576
+ try {
577
+ console.log('๐Ÿ” Testing connectivity to Onairos API...');
578
+
579
+ // Test multiple endpoints for better reliability
580
+ const testEndpoints = [
581
+ 'https://api2.onairos.uk/health',
582
+ 'https://api2.onairos.uk', // Base URL
583
+ ];
584
+
585
+ let lastError: string | null = null;
586
+
587
+ for (const endpoint of testEndpoints) {
588
+ try {
589
+ console.log(`๐Ÿ” Testing endpoint: ${endpoint}`);
590
+
591
+ const controller = new AbortController();
592
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
593
+
594
+ const response = await fetch(endpoint, {
595
+ method: 'GET',
596
+ headers: {
597
+ 'Content-Type': 'application/json',
598
+ 'User-Agent': 'OnairosReactNative/1.0',
599
+ },
600
+ signal: controller.signal,
601
+ });
602
+
603
+ clearTimeout(timeoutId);
604
+
605
+ console.log(`๐ŸŒ API connectivity test response for ${endpoint}:`, response.status);
606
+
607
+ if (response.ok || response.status === 404) {
608
+ // Accept 404 as it means the server is reachable
609
+ console.log('โœ… API server is reachable');
610
+ return { success: true };
611
+ } else {
612
+ console.log(`โš ๏ธ API server responded with status ${response.status} for ${endpoint}`);
613
+ lastError = `API server error: ${response.status}`;
614
+ // Continue to next endpoint
615
+ }
616
+ } catch (fetchError) {
617
+ console.log(`โŒ Failed to reach ${endpoint}:`, fetchError);
618
+
619
+ if (fetchError.name === 'AbortError') {
620
+ lastError = 'Connection timeout - API server took too long to respond';
621
+ } else if (fetchError.message.includes('Network request failed')) {
622
+ lastError = 'Network error - check your internet connection';
623
+ } else if (fetchError.message.includes('not connected to the internet')) {
624
+ lastError = 'No internet connection';
625
+ } else {
626
+ lastError = `Network error: ${fetchError.message}`;
627
+ }
628
+
629
+ // Continue to next endpoint
630
+ }
631
+ }
632
+
633
+ console.error('โŒ All API connectivity tests failed');
634
+ return { success: false, error: lastError || 'Cannot reach API server' };
635
+ } catch (error) {
636
+ console.error('โŒ API connectivity test failed:', error);
637
+ return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
638
+ }
639
+ };
640
+
641
+ /**
642
+ * ๐Ÿ”„ REFRESH GOOGLE TOKENS
643
+ */
644
+ export const refreshGoogleTokens = async (): Promise<{ accessToken: string; idToken?: string } | null> => {
645
+ try {
646
+ console.log('๐Ÿ”„ Attempting to refresh Google tokens...');
647
+
648
+ const { GoogleSignin } = require('@react-native-google-signin/google-signin');
649
+
650
+ const currentUser = await GoogleSignin.getCurrentUser();
651
+ if (!currentUser) {
652
+ console.log('โŒ User not signed in to Google, cannot refresh tokens');
653
+ return null;
654
+ }
655
+
656
+ const tokens = await GoogleSignin.getTokens();
657
+ console.log('โœ… Successfully refreshed Google tokens');
658
+
659
+ return {
660
+ accessToken: tokens.accessToken,
661
+ idToken: tokens.idToken
662
+ };
663
+ } catch (error) {
664
+ console.error('โŒ Failed to refresh Google tokens:', error);
665
+
666
+ // If refresh fails, try to sign in again
667
+ try {
668
+ console.log('๐Ÿ”„ Refresh failed, attempting re-authentication...');
669
+ const { GoogleSignin } = require('@react-native-google-signin/google-signin');
670
+ const userInfo = await GoogleSignin.signIn();
671
+ const tokens = await GoogleSignin.getTokens();
672
+
673
+ console.log('โœ… Re-authentication successful');
674
+ return {
675
+ accessToken: tokens.accessToken,
676
+ idToken: tokens.idToken
677
+ };
678
+ } catch (signInError) {
679
+ console.error('โŒ Re-authentication also failed:', signInError);
680
+ return null;
681
+ }
682
+ }
683
+ };
684
+
685
+ /**
686
+ * ๐Ÿ”„ REFRESH YOUTUBE TOKENS
687
+ */
688
+ export const refreshYouTubeTokens = async (): Promise<boolean> => {
689
+ try {
690
+ console.log('๐Ÿ”„ Refreshing YouTube tokens...');
691
+
692
+ // Get fresh tokens from Google SDK
693
+ const freshTokens = await refreshGoogleTokens();
694
+ if (!freshTokens) {
695
+ console.error('โŒ Failed to get fresh tokens from Google SDK');
696
+ return false;
697
+ }
698
+
699
+ // Get current user info
700
+ const { GoogleSignin } = require('@react-native-google-signin/google-signin');
701
+ const currentUser = await GoogleSignin.getCurrentUser();
702
+ if (!currentUser) {
703
+ console.error('โŒ No current Google user found');
704
+ return false;
705
+ }
706
+
707
+ // Get stored auth token
708
+ const authToken = await AsyncStorage.getItem('onairos_jwt_token') ||
709
+ await AsyncStorage.getItem('enoch_token') ||
710
+ await AsyncStorage.getItem('auth_token');
711
+
712
+ if (!authToken) {
713
+ console.error('โŒ No auth token found for YouTube refresh');
714
+ return false;
715
+ }
716
+
717
+ // Send refreshed tokens to backend
718
+ const refreshResponse = await fetch('https://api2.onairos.uk/youtube/refresh-token', {
719
+ method: 'POST',
720
+ headers: {
721
+ 'Content-Type': 'application/json',
722
+ 'Authorization': `Bearer ${authToken}`
723
+ },
724
+ body: JSON.stringify({
725
+ accessToken: freshTokens.accessToken,
726
+ idToken: freshTokens.idToken,
727
+ refreshToken: currentUser.serverAuthCode,
728
+ userEmail: currentUser.user?.email,
729
+ tokenExpiry: new Date(Date.now() + 3600 * 1000).toISOString(),
730
+ timestamp: new Date().toISOString()
731
+ })
732
+ });
733
+
734
+ if (refreshResponse.ok) {
735
+ const responseData = await refreshResponse.json();
736
+ console.log('โœ… YouTube tokens refreshed successfully:', responseData);
737
+ return true;
738
+ } else {
739
+ const errorData = await refreshResponse.text();
740
+ console.error('โŒ YouTube token refresh failed:', refreshResponse.status, errorData);
741
+ return false;
742
+ }
743
+ } catch (error) {
744
+ console.error('โŒ Error refreshing YouTube tokens:', error);
745
+ return false;
746
+ }
747
+ };
748
+
749
+ /**
750
+ * ๐ŸŽฏ ENHANCED OAUTH CALLBACK HANDLER
751
+ */
752
+ export const handleOAuthCallbackUrl = (url: string): { platform?: string; code?: string; success: boolean } => {
753
+ try {
754
+ console.log('๐Ÿ” Processing OAuth callback URL:', url);
755
+
756
+ // Parse the URL
757
+ const parsedUrl = new URL(url);
758
+
759
+ // Extract platform and code
760
+ const platform = parsedUrl.searchParams.get('platform') ||
761
+ parsedUrl.pathname.split('/').find(segment =>
762
+ ['instagram', 'youtube', 'reddit', 'pinterest', 'email'].includes(segment)
763
+ );
764
+
765
+ const code = parsedUrl.searchParams.get('code');
766
+ const error = parsedUrl.searchParams.get('error');
767
+
768
+ if (error) {
769
+ console.error('โŒ OAuth error in callback:', error);
770
+ return { success: false };
771
+ }
772
+
773
+ if (code && platform) {
774
+ console.log(`โœ… OAuth callback processed: ${platform} with code: ${code.substring(0, 10)}...`);
775
+ return { platform, code, success: true };
776
+ }
777
+
778
+ console.warn('โš ๏ธ OAuth callback missing platform or code');
779
+ return { success: false };
780
+ } catch (error) {
781
+ console.error('โŒ Error processing OAuth callback:', error);
782
+ return { success: false };
783
+ }
784
+ };
785
+
786
+ /**
787
+ * ๐Ÿ”ง UPDATE GOOGLE CLIENT IDS
788
+ * Allows apps to configure their own Google client IDs
789
+ */
790
+ export const updateGoogleClientIds = (config: {
791
+ webClientId?: string;
792
+ iosClientId?: string;
793
+ }) => {
794
+ console.log('๐Ÿ”ง Updating Google client IDs configuration');
795
+
796
+ if (config.webClientId || config.iosClientId) {
797
+ // Update the YouTube configuration
798
+ PLATFORM_AUTH_CONFIG.youtube = {
799
+ ...PLATFORM_AUTH_CONFIG.youtube,
800
+ clientId: config.webClientId || PLATFORM_AUTH_CONFIG.youtube.clientId,
801
+ iosClientId: config.iosClientId || PLATFORM_AUTH_CONFIG.youtube.iosClientId,
802
+ };
803
+
804
+ console.log('โœ… Google client IDs updated successfully');
805
+ console.log(' - Web Client ID:', config.webClientId ? config.webClientId.substring(0, 20) + '...' : 'not provided');
806
+ console.log(' - iOS Client ID:', config.iosClientId ? config.iosClientId.substring(0, 20) + '...' : 'not provided');
807
+ }
808
+ };
809
+
810
+ /**
811
+ * Request email verification using developer API key
812
+ * @param email Email address to verify
813
+ * @param testMode Whether to use test mode
814
+ * @returns Promise with verification result
815
+ */
816
+ export const requestEmailVerification = async (
817
+ email: string,
818
+ testMode: boolean = false
819
+ ): Promise<{ success: boolean; message?: string; error?: string }> => {
820
+ try {
821
+ console.log('๐Ÿ“ง Requesting email verification for:', email);
822
+
823
+ const response = await makeDeveloperRequest('/email/verification', {
824
+ method: 'POST',
825
+ body: JSON.stringify({
826
+ email,
827
+ action: 'request',
828
+ testMode
829
+ })
830
+ });
831
+
832
+ const data = await response.json();
833
+
834
+ if (response.ok && data.success) {
835
+ console.log('โœ… Email verification requested successfully');
836
+ return {
837
+ success: true,
838
+ message: data.message || 'Verification code sent to your email'
839
+ };
840
+ } else {
841
+ console.error('โŒ Email verification request failed:', data.error);
842
+ return {
843
+ success: false,
844
+ error: data.error || 'Failed to send verification code'
845
+ };
846
+ }
847
+ } catch (error) {
848
+ console.error('โŒ Error requesting email verification:', error);
849
+ return {
850
+ success: false,
851
+ error: error instanceof Error ? error.message : 'Network error'
852
+ };
853
+ }
854
+ };
855
+
856
+ /**
857
+ * Verify email code and store JWT token
858
+ * @param email Email address
859
+ * @param code Verification code
860
+ * @param testMode Whether to use test mode
861
+ * @returns Promise with verification result and JWT token
862
+ */
863
+ export const verifyEmailCode = async (
864
+ email: string,
865
+ code: string,
866
+ testMode: boolean = false
867
+ ): Promise<{ success: boolean; message?: string; error?: string; existingUser?: boolean; token?: string }> => {
868
+ try {
869
+ console.log('๐Ÿ” Verifying email code for:', email);
870
+
871
+ const response = await makeDeveloperRequest('/email/verification', {
872
+ method: 'POST',
873
+ body: JSON.stringify({
874
+ email,
875
+ action: 'verify',
876
+ code,
877
+ testMode
878
+ })
879
+ });
880
+
881
+ const data = await response.json();
882
+
883
+ if (response.ok && data.success) {
884
+ console.log('โœ… Email verification successful');
885
+
886
+ // Store JWT token if received
887
+ if (data.token || data.jwtToken) {
888
+ const jwtToken = data.token || data.jwtToken;
889
+ await storeJWT(jwtToken);
890
+ console.log('๐ŸŽซ JWT token stored successfully');
891
+ }
892
+
893
+ return {
894
+ success: true,
895
+ message: data.message || 'Email verified successfully',
896
+ existingUser: data.existingUser || false,
897
+ token: data.token || data.jwtToken
898
+ };
899
+ } else {
900
+ console.error('โŒ Email verification failed:', data.error);
901
+ return {
902
+ success: false,
903
+ error: data.error || 'Invalid verification code'
904
+ };
905
+ }
906
+ } catch (error) {
907
+ console.error('โŒ Error verifying email code:', error);
908
+ return {
909
+ success: false,
910
+ error: error instanceof Error ? error.message : 'Network error'
911
+ };
912
+ }
913
+ };
914
+
915
+ /**
916
+ * Check email verification status
917
+ * @param email Email address
918
+ * @param testMode Whether to use test mode
919
+ * @returns Promise with status result
920
+ */
921
+ export const checkEmailVerificationStatus = async (
922
+ email: string,
923
+ testMode: boolean = false
924
+ ): Promise<{ success: boolean; isPending?: boolean; error?: string }> => {
925
+ try {
926
+ console.log('๐Ÿ” Checking email verification status for:', email);
927
+
928
+ const response = await makeDeveloperRequest('/email/verification/status', {
929
+ method: 'POST',
930
+ body: JSON.stringify({
931
+ email,
932
+ testMode
933
+ })
934
+ });
935
+
936
+ const data = await response.json();
937
+
938
+ if (response.ok && data.success) {
939
+ return {
940
+ success: true,
941
+ isPending: data.isPending || false
942
+ };
943
+ } else {
944
+ return {
945
+ success: false,
946
+ error: data.error || 'Failed to check verification status'
947
+ };
948
+ }
949
+ } catch (error) {
950
+ console.error('โŒ Error checking email verification status:', error);
951
+ return {
952
+ success: false,
953
+ error: error instanceof Error ? error.message : 'Network error'
954
+ };
955
+ }
956
+ };
957
+
958
+ /**
959
+ * Disconnect a platform (uses developer API key)
960
+ * @param platform Platform to disconnect
961
+ * @param username Username associated with the platform
962
+ * @returns Promise with disconnect result
963
+ */
964
+ export const disconnectPlatform = async (platform: string, username: string): Promise<{ success: boolean; error?: string }> => {
965
+ try {
966
+ console.log('๐Ÿ”Œ Disconnecting platform:', platform, 'for user:', username);
967
+
968
+ // Make authenticated API call to disconnect platform
969
+ const response = await makeDeveloperRequest('/revoke', {
970
+ method: 'POST',
971
+ body: JSON.stringify({
972
+ platform,
973
+ username
974
+ })
975
+ });
976
+
977
+ const data = await response.json();
978
+
979
+ if (response.ok && data.success) {
980
+ console.log(`โœ… ${platform} disconnected successfully`);
981
+ return { success: true };
982
+ } else {
983
+ console.error(`โŒ Failed to disconnect ${platform}:`, data.error);
984
+ return {
985
+ success: false,
986
+ error: data.error || 'Failed to disconnect platform'
987
+ };
988
+ }
989
+ } catch (error) {
990
+ console.error(`โŒ Error disconnecting ${platform}:`, error);
991
+ return {
992
+ success: false,
993
+ error: error instanceof Error ? error.message : 'Network error'
994
+ };
995
+ }
996
+ };
997
+
998
+ /**
999
+ * Store PIN for user (uses JWT authentication and extracts username from JWT)
1000
+ * @param pin User PIN
1001
+ * @param username Optional username (if not provided, extracts from JWT)
1002
+ * @returns Promise with result
1003
+ */
1004
+ export const storePIN = async (pin: string, username?: string): Promise<{ success: boolean; error?: string }> => {
1005
+ try {
1006
+ // Extract username from JWT if not provided
1007
+ const userToStore = username || extractUsernameFromJWT();
1008
+
1009
+ if (!userToStore) {
1010
+ console.error('โŒ No username available - either provide username or ensure JWT token is valid');
1011
+ return {
1012
+ success: false,
1013
+ error: 'No username available for PIN storage'
1014
+ };
1015
+ }
1016
+
1017
+ console.log('๐Ÿ” Storing PIN for user:', userToStore);
1018
+
1019
+ // Make authenticated request to store PIN (using developer API key for now)
1020
+ const response = await makeDeveloperRequest('/store-pin/web', {
1021
+ method: 'POST',
1022
+ headers: {
1023
+ 'Content-Type': 'application/json',
1024
+ },
1025
+ body: JSON.stringify({
1026
+ username: userToStore,
1027
+ pin
1028
+ })
1029
+ });
1030
+
1031
+ const data = await response.json();
1032
+
1033
+ if (response.ok && data.success) {
1034
+ console.log('โœ… PIN stored successfully for user:', userToStore);
1035
+ return { success: true };
1036
+ } else {
1037
+ console.error('โŒ Failed to store PIN:', data.error);
1038
+ return {
1039
+ success: false,
1040
+ error: data.error || 'Failed to store PIN'
1041
+ };
1042
+ }
1043
+ } catch (error) {
1044
+ console.error('โŒ Error storing PIN:', error);
1045
+ return {
1046
+ success: false,
1047
+ error: error instanceof Error ? error.message : 'Network error'
1048
+ };
1049
+ }
1050
+ };
1051
+
1052
+ /**
1053
+ * ๐ŸŽซ GET STORED JWT TOKEN
1054
+ * Helper function to retrieve stored JWT token from email verification or other sources
1055
+ */
1056
+ export const getStoredJwtToken = async (): Promise<string | null> => {
1057
+ try {
1058
+ console.log('๐ŸŽซ Retrieving stored JWT token...');
1059
+
1060
+ // Try different storage keys in order of preference
1061
+ const tokenSources = [
1062
+ 'email_verification_token',
1063
+ 'onairos_jwt_token',
1064
+ 'enoch_token',
1065
+ 'auth_token',
1066
+ ];
1067
+
1068
+ for (const source of tokenSources) {
1069
+ const token = await AsyncStorage.getItem(source);
1070
+ if (token && token.length > 20) {
1071
+ console.log(`โœ… JWT token found in ${source}:`, token.substring(0, 20) + '...');
1072
+ return token;
1073
+ }
1074
+ }
1075
+
1076
+ console.warn('โš ๏ธ No JWT token found in storage');
1077
+ return null;
1078
+ } catch (error) {
1079
+ console.error('โŒ Error retrieving JWT token:', error);
1080
+ return null;
1081
+ }
1082
+ };
1083
+
1084
+ /**
1085
+ * ๐ŸŽซ CLEAR STORED TOKENS
1086
+ * Helper function to clear all stored tokens (useful for logout)
1087
+ */
1088
+ export const clearStoredTokens = async (): Promise<void> => {
1089
+ try {
1090
+ console.log('๐Ÿงน Clearing all stored tokens...');
1091
+
1092
+ const tokenKeys = [
1093
+ 'email_verification_token',
1094
+ 'onairos_jwt_token',
1095
+ 'enoch_token',
1096
+ 'auth_token',
1097
+ 'email_verification_email',
1098
+ 'email_verification_request_id',
1099
+ 'email_verification_request_email',
1100
+ 'token_timestamp',
1101
+ 'user_pin_stored',
1102
+ 'pin_storage_timestamp',
1103
+ ];
1104
+
1105
+ await Promise.all(
1106
+ tokenKeys.map(key => AsyncStorage.removeItem(key))
1107
+ );
1108
+
1109
+ console.log('โœ… All tokens cleared successfully');
1110
+ } catch (error) {
1111
+ console.error('โŒ Error clearing tokens:', error);
1112
+ }
1113
+ };