@oxyhq/services 10.5.0 → 11.1.0

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 (427) hide show
  1. package/lib/commonjs/index.js.map +1 -1
  2. package/lib/commonjs/ui/components/AccountMenu.js +9 -5
  3. package/lib/commonjs/ui/components/AccountMenu.js.map +1 -1
  4. package/lib/commonjs/ui/components/AnotherDeviceQR.js +51 -56
  5. package/lib/commonjs/ui/components/AnotherDeviceQR.js.map +1 -1
  6. package/lib/commonjs/ui/components/BottomSheetRouter.js +1 -0
  7. package/lib/commonjs/ui/components/BottomSheetRouter.js.map +1 -1
  8. package/lib/commonjs/ui/components/FollowButton.js +18 -5
  9. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  10. package/lib/commonjs/ui/components/OxyProvider.js +23 -7
  11. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  12. package/lib/commonjs/ui/components/SignInModal.js +20 -1
  13. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  14. package/lib/commonjs/ui/components/fileManagement/FileViewer.js +19 -9
  15. package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
  16. package/lib/commonjs/ui/components/fileManagement/UploadPreview.js +4 -2
  17. package/lib/commonjs/ui/components/fileManagement/UploadPreview.js.map +1 -1
  18. package/lib/commonjs/ui/context/OxyContext.js +153 -19
  19. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  20. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +6 -17
  21. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  22. package/lib/commonjs/ui/hooks/mutations/mutationFactory.js +5 -5
  23. package/lib/commonjs/ui/hooks/mutations/mutationFactory.js.map +1 -1
  24. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +38 -38
  25. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  26. package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js +2 -2
  27. package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js.map +1 -1
  28. package/lib/commonjs/ui/hooks/queries/queryKeys.js +3 -3
  29. package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
  30. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +1 -1
  31. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  32. package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js +16 -12
  33. package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js.map +1 -1
  34. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +10 -6
  35. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
  36. package/lib/commonjs/ui/hooks/queryClient.js +6 -5
  37. package/lib/commonjs/ui/hooks/queryClient.js.map +1 -1
  38. package/lib/commonjs/ui/hooks/useOxyAuthSession.js +40 -2
  39. package/lib/commonjs/ui/hooks/useOxyAuthSession.js.map +1 -1
  40. package/lib/commonjs/ui/hooks/useProfileEditing.js +21 -0
  41. package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
  42. package/lib/commonjs/ui/hooks/useSessionManagement.js +3 -3
  43. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  44. package/lib/commonjs/ui/screens/AccountVerificationScreen.js +100 -108
  45. package/lib/commonjs/ui/screens/AccountVerificationScreen.js.map +1 -1
  46. package/lib/commonjs/ui/screens/AppInfoScreen.js +227 -273
  47. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  48. package/lib/commonjs/ui/screens/AvatarCropScreen.js +10 -4
  49. package/lib/commonjs/ui/screens/AvatarCropScreen.js.map +1 -1
  50. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js +20 -37
  51. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js.map +1 -1
  52. package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js +89 -201
  53. package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js.map +1 -1
  54. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +80 -208
  55. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
  56. package/lib/commonjs/ui/screens/FAQScreen.js +56 -208
  57. package/lib/commonjs/ui/screens/FAQScreen.js.map +1 -1
  58. package/lib/commonjs/ui/screens/FeedbackScreen.js +303 -352
  59. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  60. package/lib/commonjs/ui/screens/FileManagementScreen.js +20 -20
  61. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  62. package/lib/commonjs/ui/screens/HelpSupportScreen.js +77 -89
  63. package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
  64. package/lib/commonjs/ui/screens/HistoryViewScreen.js +43 -58
  65. package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
  66. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +67 -90
  67. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  68. package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js +77 -177
  69. package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
  70. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js +113 -107
  71. package/lib/commonjs/ui/screens/LegalDocumentsScreen.js.map +1 -1
  72. package/lib/commonjs/ui/screens/ManageAccountScreen.js +55 -114
  73. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  74. package/lib/commonjs/ui/screens/NotificationsScreen.js +67 -85
  75. package/lib/commonjs/ui/screens/NotificationsScreen.js.map +1 -1
  76. package/lib/commonjs/ui/screens/OxyAuthScreen.js +71 -135
  77. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  78. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +15 -9
  79. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  80. package/lib/commonjs/ui/screens/PreferencesScreen.js +65 -83
  81. package/lib/commonjs/ui/screens/PreferencesScreen.js.map +1 -1
  82. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +378 -1023
  83. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  84. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +294 -242
  85. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  86. package/lib/commonjs/ui/screens/ProfileScreen.js +192 -305
  87. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  88. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js +57 -97
  89. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
  90. package/lib/commonjs/ui/screens/SearchSettingsScreen.js +41 -41
  91. package/lib/commonjs/ui/screens/SearchSettingsScreen.js.map +1 -1
  92. package/lib/commonjs/ui/screens/UserLinksScreen.js +17 -24
  93. package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -1
  94. package/lib/commonjs/ui/screens/UserListScreen.js +83 -214
  95. package/lib/commonjs/ui/screens/UserListScreen.js.map +1 -1
  96. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +115 -77
  97. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  98. package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js +70 -57
  99. package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js.map +1 -1
  100. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +136 -332
  101. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  102. package/lib/commonjs/ui/screens/trust/TrustFAQScreen.js +47 -137
  103. package/lib/commonjs/ui/screens/trust/TrustFAQScreen.js.map +1 -1
  104. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +182 -115
  105. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  106. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +138 -214
  107. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  108. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js +54 -92
  109. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  110. package/lib/commonjs/ui/utils/activeAuthuser.js +15 -9
  111. package/lib/commonjs/ui/utils/activeAuthuser.js.map +1 -1
  112. package/lib/commonjs/ui/utils/avatarUtils.js +1 -1
  113. package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
  114. package/lib/module/index.js.map +1 -1
  115. package/lib/module/ui/components/AccountMenu.js +10 -6
  116. package/lib/module/ui/components/AccountMenu.js.map +1 -1
  117. package/lib/module/ui/components/AnotherDeviceQR.js +50 -56
  118. package/lib/module/ui/components/AnotherDeviceQR.js.map +1 -1
  119. package/lib/module/ui/components/BottomSheetRouter.js +2 -1
  120. package/lib/module/ui/components/BottomSheetRouter.js.map +1 -1
  121. package/lib/module/ui/components/FollowButton.js +18 -5
  122. package/lib/module/ui/components/FollowButton.js.map +1 -1
  123. package/lib/module/ui/components/OxyProvider.js +23 -7
  124. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  125. package/lib/module/ui/components/SignInModal.js +20 -1
  126. package/lib/module/ui/components/SignInModal.js.map +1 -1
  127. package/lib/module/ui/components/fileManagement/FileViewer.js +19 -9
  128. package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
  129. package/lib/module/ui/components/fileManagement/UploadPreview.js +4 -2
  130. package/lib/module/ui/components/fileManagement/UploadPreview.js.map +1 -1
  131. package/lib/module/ui/context/OxyContext.js +154 -20
  132. package/lib/module/ui/context/OxyContext.js.map +1 -1
  133. package/lib/module/ui/context/hooks/useAuthOperations.js +6 -17
  134. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  135. package/lib/module/ui/hooks/mutations/mutationFactory.js +5 -5
  136. package/lib/module/ui/hooks/mutations/mutationFactory.js.map +1 -1
  137. package/lib/module/ui/hooks/mutations/useAccountMutations.js +38 -38
  138. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  139. package/lib/module/ui/hooks/mutations/useServicesMutations.js +2 -2
  140. package/lib/module/ui/hooks/mutations/useServicesMutations.js.map +1 -1
  141. package/lib/module/ui/hooks/queries/queryKeys.js +3 -3
  142. package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
  143. package/lib/module/ui/hooks/queries/useAccountQueries.js +1 -1
  144. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  145. package/lib/module/ui/hooks/queries/usePaymentQueries.js +16 -12
  146. package/lib/module/ui/hooks/queries/usePaymentQueries.js.map +1 -1
  147. package/lib/module/ui/hooks/queries/useServicesQueries.js +9 -6
  148. package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
  149. package/lib/module/ui/hooks/queryClient.js +6 -5
  150. package/lib/module/ui/hooks/queryClient.js.map +1 -1
  151. package/lib/module/ui/hooks/useOxyAuthSession.js +40 -2
  152. package/lib/module/ui/hooks/useOxyAuthSession.js.map +1 -1
  153. package/lib/module/ui/hooks/useProfileEditing.js +21 -0
  154. package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
  155. package/lib/module/ui/hooks/useSessionManagement.js +4 -3
  156. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  157. package/lib/module/ui/screens/AccountVerificationScreen.js +101 -109
  158. package/lib/module/ui/screens/AccountVerificationScreen.js.map +1 -1
  159. package/lib/module/ui/screens/AppInfoScreen.js +228 -275
  160. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  161. package/lib/module/ui/screens/AvatarCropScreen.js +10 -4
  162. package/lib/module/ui/screens/AvatarCropScreen.js.map +1 -1
  163. package/lib/module/ui/screens/ConnectedAppsScreen.js +19 -39
  164. package/lib/module/ui/screens/ConnectedAppsScreen.js.map +1 -1
  165. package/lib/module/ui/screens/CreateManagedAccountScreen.js +90 -202
  166. package/lib/module/ui/screens/CreateManagedAccountScreen.js.map +1 -1
  167. package/lib/module/ui/screens/EditProfileFieldScreen.js +77 -205
  168. package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
  169. package/lib/module/ui/screens/FAQScreen.js +55 -207
  170. package/lib/module/ui/screens/FAQScreen.js.map +1 -1
  171. package/lib/module/ui/screens/FeedbackScreen.js +301 -350
  172. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  173. package/lib/module/ui/screens/FileManagementScreen.js +20 -20
  174. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  175. package/lib/module/ui/screens/HelpSupportScreen.js +78 -90
  176. package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
  177. package/lib/module/ui/screens/HistoryViewScreen.js +44 -59
  178. package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
  179. package/lib/module/ui/screens/LanguageSelectorScreen.js +68 -91
  180. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  181. package/lib/module/ui/screens/LearnMoreUsernamesScreen.js +75 -177
  182. package/lib/module/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
  183. package/lib/module/ui/screens/LegalDocumentsScreen.js +116 -108
  184. package/lib/module/ui/screens/LegalDocumentsScreen.js.map +1 -1
  185. package/lib/module/ui/screens/ManageAccountScreen.js +52 -112
  186. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  187. package/lib/module/ui/screens/NotificationsScreen.js +68 -86
  188. package/lib/module/ui/screens/NotificationsScreen.js.map +1 -1
  189. package/lib/module/ui/screens/OxyAuthScreen.js +69 -134
  190. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  191. package/lib/module/ui/screens/PaymentGatewayScreen.js +16 -10
  192. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  193. package/lib/module/ui/screens/PreferencesScreen.js +66 -84
  194. package/lib/module/ui/screens/PreferencesScreen.js.map +1 -1
  195. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +366 -1012
  196. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  197. package/lib/module/ui/screens/PrivacySettingsScreen.js +295 -243
  198. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  199. package/lib/module/ui/screens/ProfileScreen.js +189 -302
  200. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  201. package/lib/module/ui/screens/SavesCollectionsScreen.js +58 -98
  202. package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
  203. package/lib/module/ui/screens/SearchSettingsScreen.js +42 -42
  204. package/lib/module/ui/screens/SearchSettingsScreen.js.map +1 -1
  205. package/lib/module/ui/screens/UserLinksScreen.js +18 -25
  206. package/lib/module/ui/screens/UserLinksScreen.js.map +1 -1
  207. package/lib/module/ui/screens/UserListScreen.js +81 -212
  208. package/lib/module/ui/screens/UserListScreen.js.map +1 -1
  209. package/lib/module/ui/screens/WelcomeNewUserScreen.js +114 -76
  210. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  211. package/lib/module/ui/screens/trust/TrustAboutScreen.js +69 -57
  212. package/lib/module/ui/screens/trust/TrustAboutScreen.js.map +1 -1
  213. package/lib/module/ui/screens/trust/TrustCenterScreen.js +135 -332
  214. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  215. package/lib/module/ui/screens/trust/TrustFAQScreen.js +48 -138
  216. package/lib/module/ui/screens/trust/TrustFAQScreen.js.map +1 -1
  217. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +184 -117
  218. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  219. package/lib/module/ui/screens/trust/TrustRewardsScreen.js +132 -208
  220. package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  221. package/lib/module/ui/screens/trust/TrustRulesScreen.js +58 -94
  222. package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  223. package/lib/module/ui/utils/activeAuthuser.js +15 -9
  224. package/lib/module/ui/utils/activeAuthuser.js.map +1 -1
  225. package/lib/module/ui/utils/avatarUtils.js +1 -1
  226. package/lib/module/ui/utils/avatarUtils.js.map +1 -1
  227. package/lib/typescript/commonjs/index.d.ts +1 -0
  228. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  229. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +2 -0
  230. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +1 -1
  231. package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts +12 -2
  232. package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/ui/components/BottomSheetRouter.d.ts.map +1 -1
  234. package/lib/typescript/commonjs/ui/components/FollowButton.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts +3 -2
  236. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
  237. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  238. package/lib/typescript/commonjs/ui/components/TouchableRipple/TouchableRipple.native.d.ts +1 -1
  239. package/lib/typescript/commonjs/ui/components/TouchableRipple/TouchableRipple.native.d.ts.map +1 -1
  240. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +34 -0
  241. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  242. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  243. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +3 -0
  244. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  245. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts +3 -3
  246. package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  247. package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  248. package/lib/typescript/commonjs/ui/hooks/queryClient.d.ts.map +1 -1
  249. package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts +22 -0
  250. package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
  251. package/lib/typescript/commonjs/ui/hooks/useProfileEditing.d.ts +3 -0
  252. package/lib/typescript/commonjs/ui/hooks/useProfileEditing.d.ts.map +1 -1
  253. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts +2 -1
  254. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
  255. package/lib/typescript/commonjs/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
  256. package/lib/typescript/commonjs/ui/screens/AppInfoScreen.d.ts.map +1 -1
  257. package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts.map +1 -1
  258. package/lib/typescript/commonjs/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  259. package/lib/typescript/commonjs/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -1
  260. package/lib/typescript/commonjs/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  261. package/lib/typescript/commonjs/ui/screens/FAQScreen.d.ts.map +1 -1
  262. package/lib/typescript/commonjs/ui/screens/FeedbackScreen.d.ts.map +1 -1
  263. package/lib/typescript/commonjs/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  264. package/lib/typescript/commonjs/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  265. package/lib/typescript/commonjs/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  266. package/lib/typescript/commonjs/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
  267. package/lib/typescript/commonjs/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  268. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  269. package/lib/typescript/commonjs/ui/screens/NotificationsScreen.d.ts.map +1 -1
  270. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  271. package/lib/typescript/commonjs/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  272. package/lib/typescript/commonjs/ui/screens/PreferencesScreen.d.ts.map +1 -1
  273. package/lib/typescript/commonjs/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  274. package/lib/typescript/commonjs/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  275. package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
  276. package/lib/typescript/commonjs/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  277. package/lib/typescript/commonjs/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  278. package/lib/typescript/commonjs/ui/screens/UserLinksScreen.d.ts.map +1 -1
  279. package/lib/typescript/commonjs/ui/screens/UserListScreen.d.ts.map +1 -1
  280. package/lib/typescript/commonjs/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  281. package/lib/typescript/commonjs/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
  282. package/lib/typescript/commonjs/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
  283. package/lib/typescript/commonjs/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
  284. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  285. package/lib/typescript/commonjs/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
  286. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  287. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +1 -1
  288. package/lib/typescript/module/index.d.ts +1 -0
  289. package/lib/typescript/module/index.d.ts.map +1 -1
  290. package/lib/typescript/module/ui/components/AccountMenu.d.ts +2 -0
  291. package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +1 -1
  292. package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts +12 -2
  293. package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts.map +1 -1
  294. package/lib/typescript/module/ui/components/BottomSheetRouter.d.ts.map +1 -1
  295. package/lib/typescript/module/ui/components/FollowButton.d.ts.map +1 -1
  296. package/lib/typescript/module/ui/components/OxyProvider.d.ts +3 -2
  297. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  298. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  299. package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.native.d.ts +1 -1
  300. package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.native.d.ts.map +1 -1
  301. package/lib/typescript/module/ui/context/OxyContext.d.ts +34 -0
  302. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  303. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  304. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +3 -0
  305. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  306. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts +3 -3
  307. package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts.map +1 -1
  308. package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  309. package/lib/typescript/module/ui/hooks/queryClient.d.ts.map +1 -1
  310. package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts +22 -0
  311. package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
  312. package/lib/typescript/module/ui/hooks/useProfileEditing.d.ts +3 -0
  313. package/lib/typescript/module/ui/hooks/useProfileEditing.d.ts.map +1 -1
  314. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +2 -1
  315. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  316. package/lib/typescript/module/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
  317. package/lib/typescript/module/ui/screens/AppInfoScreen.d.ts.map +1 -1
  318. package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts.map +1 -1
  319. package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  320. package/lib/typescript/module/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -1
  321. package/lib/typescript/module/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  322. package/lib/typescript/module/ui/screens/FAQScreen.d.ts.map +1 -1
  323. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
  324. package/lib/typescript/module/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  325. package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts.map +1 -1
  326. package/lib/typescript/module/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  327. package/lib/typescript/module/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
  328. package/lib/typescript/module/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
  329. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  330. package/lib/typescript/module/ui/screens/NotificationsScreen.d.ts.map +1 -1
  331. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  332. package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  333. package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts.map +1 -1
  334. package/lib/typescript/module/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  335. package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  336. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  337. package/lib/typescript/module/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  338. package/lib/typescript/module/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
  339. package/lib/typescript/module/ui/screens/UserLinksScreen.d.ts.map +1 -1
  340. package/lib/typescript/module/ui/screens/UserListScreen.d.ts.map +1 -1
  341. package/lib/typescript/module/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  342. package/lib/typescript/module/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
  343. package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
  344. package/lib/typescript/module/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
  345. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  346. package/lib/typescript/module/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
  347. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  348. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +1 -1
  349. package/lib/typescript/types/expo-haptics.d.ts +42 -0
  350. package/package.json +24 -31
  351. package/src/index.ts +1 -0
  352. package/src/types/expo-haptics.d.ts +42 -0
  353. package/src/ui/components/AccountMenu.tsx +11 -5
  354. package/src/ui/components/AnotherDeviceQR.tsx +53 -45
  355. package/src/ui/components/BottomSheetRouter.tsx +2 -1
  356. package/src/ui/components/FollowButton.tsx +24 -5
  357. package/src/ui/components/OxyProvider.tsx +22 -8
  358. package/src/ui/components/SignInModal.tsx +21 -2
  359. package/src/ui/components/TouchableRipple/TouchableRipple.native.tsx +1 -1
  360. package/src/ui/components/fileManagement/FileViewer.tsx +9 -9
  361. package/src/ui/components/fileManagement/UploadPreview.tsx +2 -2
  362. package/src/ui/context/OxyContext.tsx +178 -21
  363. package/src/ui/context/hooks/useAuthOperations.ts +6 -17
  364. package/src/ui/hooks/mutations/mutationFactory.ts +5 -5
  365. package/src/ui/hooks/mutations/useAccountMutations.ts +38 -38
  366. package/src/ui/hooks/mutations/useServicesMutations.ts +2 -2
  367. package/src/ui/hooks/queries/queryKeys.ts +6 -3
  368. package/src/ui/hooks/queries/useAccountQueries.ts +1 -1
  369. package/src/ui/hooks/queries/usePaymentQueries.ts +12 -12
  370. package/src/ui/hooks/queries/useServicesQueries.ts +9 -6
  371. package/src/ui/hooks/queryClient.ts +5 -5
  372. package/src/ui/hooks/useOxyAuthSession.ts +76 -2
  373. package/src/ui/hooks/useProfileEditing.ts +24 -0
  374. package/src/ui/hooks/useSessionManagement.ts +9 -6
  375. package/src/ui/screens/AccountVerificationScreen.tsx +101 -113
  376. package/src/ui/screens/AppInfoScreen.tsx +200 -238
  377. package/src/ui/screens/AvatarCropScreen.tsx +17 -4
  378. package/src/ui/screens/ConnectedAppsScreen.tsx +16 -34
  379. package/src/ui/screens/CreateManagedAccountScreen.tsx +94 -170
  380. package/src/ui/screens/EditProfileFieldScreen.tsx +77 -190
  381. package/src/ui/screens/FAQScreen.tsx +77 -208
  382. package/src/ui/screens/FeedbackScreen.tsx +330 -239
  383. package/src/ui/screens/FileManagementScreen.tsx +20 -20
  384. package/src/ui/screens/HelpSupportScreen.tsx +67 -82
  385. package/src/ui/screens/HistoryViewScreen.tsx +32 -38
  386. package/src/ui/screens/LanguageSelectorScreen.tsx +79 -93
  387. package/src/ui/screens/LearnMoreUsernamesScreen.tsx +81 -164
  388. package/src/ui/screens/LegalDocumentsScreen.tsx +184 -123
  389. package/src/ui/screens/ManageAccountScreen.tsx +48 -114
  390. package/src/ui/screens/NotificationsScreen.tsx +107 -106
  391. package/src/ui/screens/OxyAuthScreen.tsx +76 -109
  392. package/src/ui/screens/PaymentGatewayScreen.tsx +16 -7
  393. package/src/ui/screens/PreferencesScreen.tsx +96 -116
  394. package/src/ui/screens/PremiumSubscriptionScreen.tsx +419 -872
  395. package/src/ui/screens/PrivacySettingsScreen.tsx +203 -185
  396. package/src/ui/screens/ProfileScreen.tsx +158 -200
  397. package/src/ui/screens/SavesCollectionsScreen.tsx +78 -125
  398. package/src/ui/screens/SearchSettingsScreen.tsx +52 -41
  399. package/src/ui/screens/UserLinksScreen.tsx +18 -25
  400. package/src/ui/screens/UserListScreen.tsx +95 -188
  401. package/src/ui/screens/WelcomeNewUserScreen.tsx +109 -36
  402. package/src/ui/screens/trust/TrustAboutScreen.tsx +52 -41
  403. package/src/ui/screens/trust/TrustCenterScreen.tsx +184 -222
  404. package/src/ui/screens/trust/TrustFAQScreen.tsx +64 -124
  405. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +190 -67
  406. package/src/ui/screens/trust/TrustRewardsScreen.tsx +147 -182
  407. package/src/ui/screens/trust/TrustRulesScreen.tsx +77 -50
  408. package/src/ui/utils/activeAuthuser.ts +15 -9
  409. package/src/ui/utils/avatarUtils.ts +1 -1
  410. package/lib/commonjs/ui/components/feedback/FormInput.js +0 -72
  411. package/lib/commonjs/ui/components/feedback/FormInput.js.map +0 -1
  412. package/lib/commonjs/ui/components/feedback/feedbackStyles.js +0 -261
  413. package/lib/commonjs/ui/components/feedback/feedbackStyles.js.map +0 -1
  414. package/lib/module/ui/components/feedback/FormInput.js +0 -67
  415. package/lib/module/ui/components/feedback/FormInput.js.map +0 -1
  416. package/lib/module/ui/components/feedback/feedbackStyles.js +0 -256
  417. package/lib/module/ui/components/feedback/feedbackStyles.js.map +0 -1
  418. package/lib/typescript/commonjs/ui/components/feedback/FormInput.d.ts +0 -20
  419. package/lib/typescript/commonjs/ui/components/feedback/FormInput.d.ts.map +0 -1
  420. package/lib/typescript/commonjs/ui/components/feedback/feedbackStyles.d.ts +0 -279
  421. package/lib/typescript/commonjs/ui/components/feedback/feedbackStyles.d.ts.map +0 -1
  422. package/lib/typescript/module/ui/components/feedback/FormInput.d.ts +0 -20
  423. package/lib/typescript/module/ui/components/feedback/FormInput.d.ts.map +0 -1
  424. package/lib/typescript/module/ui/components/feedback/feedbackStyles.d.ts +0 -279
  425. package/lib/typescript/module/ui/components/feedback/feedbackStyles.d.ts.map +0 -1
  426. package/src/ui/components/feedback/FormInput.tsx +0 -84
  427. package/src/ui/components/feedback/feedbackStyles.ts +0 -246
@@ -1,24 +1,25 @@
1
1
  import type React from 'react';
2
2
  import { useState, useEffect, useCallback, useMemo } from 'react';
3
- import {
4
- View,
5
- Text,
6
- TouchableOpacity,
7
- StyleSheet,
8
- ScrollView,
9
- ActivityIndicator,
10
- Platform,
11
- Animated,
12
- Dimensions,
13
- } from 'react-native';
3
+ import { View, ScrollView, ActivityIndicator } from 'react-native';
14
4
  import type { BaseScreenProps } from '../types/navigation';
15
5
  import { Dialog, toast, useDialogControl } from '@oxyhq/bloom';
6
+ import { useTheme } from '@oxyhq/bloom/theme';
7
+ import { Button } from '@oxyhq/bloom/button';
8
+ import { Chip } from '@oxyhq/bloom/chip';
9
+ import { H2, H4, H5, Text } from '@oxyhq/bloom/typography';
10
+ import { BenefitList, BenefitRow } from '@oxyhq/bloom/benefit-list';
11
+ import {
12
+ SegmentedControl,
13
+ SegmentedControlItem,
14
+ SegmentedControlItemText,
15
+ } from '@oxyhq/bloom/segmented-control';
16
16
  import { Ionicons } from '@expo/vector-icons';
17
- import Avatar from '../components/Avatar';
17
+ import Header from '../components/Header';
18
18
  import { useI18n } from '../hooks/useI18n';
19
- import { useTheme } from '@oxyhq/bloom/theme';
20
19
  import { useOxy } from '../context/OxyContext';
21
20
 
21
+ type IoniconName = React.ComponentProps<typeof Ionicons>['name'];
22
+
22
23
  interface SubscriptionPlan {
23
24
  id: string;
24
25
  name: string;
@@ -60,43 +61,57 @@ interface UserSubscription {
60
61
  trialEnd?: string;
61
62
  }
62
63
 
64
+ const TAB_PLANS = 'plans';
65
+ const TAB_FEATURES = 'features';
66
+ type ActiveTab = typeof TAB_PLANS | typeof TAB_FEATURES;
67
+
68
+ const BILLING_MONTH = 'month';
69
+ const BILLING_YEAR = 'year';
70
+ type BillingInterval = typeof BILLING_MONTH | typeof BILLING_YEAR;
71
+
72
+ /** Yearly billing discount applied when extrapolating a monthly price. */
73
+ const YEARLY_DISCOUNT = 0.8;
74
+ const MONTHS_PER_YEAR = 12;
75
+ /** Simulated payment latency for the mocked subscribe/feature flows (ms). */
76
+ const SUBSCRIBE_DELAY_MS = 2000;
77
+ const FEATURE_DELAY_MS = 1500;
78
+ /** One subscription period for the mocked renewal date (30 days, in ms). */
79
+ const PERIOD_MS = 30 * 24 * 60 * 60 * 1000;
80
+
81
+ const FEATURE_CATEGORIES: IndividualFeature['category'][] = [
82
+ 'analytics',
83
+ 'customization',
84
+ 'content',
85
+ 'networking',
86
+ 'productivity',
87
+ ];
88
+
63
89
  const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
64
90
  onClose,
65
- theme,
66
91
  navigate,
67
92
  goBack,
68
93
  }) => {
69
94
  // Use useOxy() hook for OxyContext values
70
- const { user, oxyServices } = useOxy();
95
+ const { user } = useOxy();
71
96
  const [loading, setLoading] = useState(true);
72
97
  const [subscription, setSubscription] = useState<UserSubscription | null>(null);
73
98
  const [plans, setPlans] = useState<SubscriptionPlan[]>([]);
74
99
  const [individualFeatures, setIndividualFeatures] = useState<IndividualFeature[]>([]);
75
100
  const [selectedPlan, setSelectedPlan] = useState<string | null>(null);
76
101
  const [processingPayment, setProcessingPayment] = useState(false);
77
- const [billingInterval, setBillingInterval] = useState<'month' | 'year'>('month');
78
- const [activeTab, setActiveTab] = useState<'plans' | 'features'>('plans');
102
+ const [billingInterval, setBillingInterval] = useState<BillingInterval>(BILLING_MONTH);
103
+ const [activeTab, setActiveTab] = useState<ActiveTab>(TAB_PLANS);
79
104
  const [currentAppPackage, setCurrentAppPackage] = useState<string>('mention'); // Default to mention for demo
80
105
  const [pendingUnsubscribeFeatureId, setPendingUnsubscribeFeatureId] = useState<string | null>(null);
81
106
 
82
107
  const { t } = useI18n();
83
108
  const bloomTheme = useTheme();
109
+ const colors = bloomTheme.colors;
84
110
 
85
111
  // Prompt controls
86
112
  const cancelSubscriptionDialog = useDialogControl();
87
113
  const unsubscribeFeatureDialog = useDialogControl();
88
114
 
89
- // Extract commonly used colors for readability
90
- const textColor = bloomTheme.colors.text;
91
- const backgroundColor = bloomTheme.colors.background;
92
- const secondaryBackgroundColor = bloomTheme.colors.backgroundSecondary;
93
- const borderColor = bloomTheme.colors.border;
94
- const primaryColor = bloomTheme.colors.primary;
95
- const successColor = bloomTheme.colors.success;
96
- const dangerColor = bloomTheme.colors.error;
97
- const isDarkTheme = bloomTheme.isDark;
98
- const warningColor = bloomTheme.colors.warning;
99
-
100
115
  // Oxy+ subscription plans
101
116
  const mockPlans: SubscriptionPlan[] = [
102
117
  {
@@ -336,7 +351,7 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
336
351
  planId: 'oxy-insider',
337
352
  status: 'active',
338
353
  currentPeriodStart: new Date().toISOString(),
339
- currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
354
+ currentPeriodEnd: new Date(Date.now() + PERIOD_MS).toISOString(),
340
355
  cancelAtPeriodEnd: false
341
356
  };
342
357
  setSubscription(currentSubscription);
@@ -369,14 +384,10 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
369
384
  }
370
385
  };
371
386
 
372
- const handlePlanSelection = (planId: string) => {
373
- setSelectedPlan(planId);
374
- };
375
-
376
387
  const handleSubscribe = async (planId: string) => {
377
388
  try {
378
- const selectedPlan = mockPlans.find(plan => plan.id === planId);
379
- if (!selectedPlan?.applicableApps.includes(currentAppPackage)) {
389
+ const planToSubscribe = mockPlans.find(plan => plan.id === planId);
390
+ if (!planToSubscribe?.applicableApps.includes(currentAppPackage)) {
380
391
  toast.error(t('premium.toasts.planUnavailable', { app: currentAppPackage }) || `This plan is not available for the current app (${currentAppPackage})`);
381
392
  return;
382
393
  }
@@ -386,8 +397,9 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
386
397
  return;
387
398
  }
388
399
 
400
+ setSelectedPlan(planId);
389
401
  setProcessingPayment(true);
390
- await new Promise(resolve => setTimeout(resolve, 2000));
402
+ await new Promise(resolve => setTimeout(resolve, SUBSCRIBE_DELAY_MS));
391
403
  toast.success(t('premium.toasts.activated') || 'Subscription activated successfully!');
392
404
 
393
405
  setSubscription({
@@ -395,7 +407,7 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
395
407
  planId,
396
408
  status: 'active',
397
409
  currentPeriodStart: new Date().toISOString(),
398
- currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
410
+ currentPeriodEnd: new Date(Date.now() + PERIOD_MS).toISOString(),
399
411
  cancelAtPeriodEnd: false
400
412
  });
401
413
 
@@ -427,7 +439,7 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
427
439
  }
428
440
  }, [t]);
429
441
 
430
- const handleReactivateSubscription = async () => {
442
+ const handleReactivateSubscription = useCallback(async () => {
431
443
  try {
432
444
  setSubscription(prev => prev ? {
433
445
  ...prev,
@@ -437,10 +449,10 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
437
449
  } catch (error) {
438
450
  toast.error(t('premium.toasts.reactivateFailed') || 'Failed to reactivate subscription');
439
451
  }
440
- };
452
+ }, [t]);
441
453
 
442
- const formatPrice = (price: number, currency: string, interval: string) => {
443
- const yearlyPrice = interval === 'year' ? price : price * 12 * 0.8;
454
+ const formatPrice = (price: number, interval: string) => {
455
+ const yearlyPrice = interval === 'year' ? price : price * MONTHS_PER_YEAR * YEARLY_DISCOUNT;
444
456
  const displayPrice = billingInterval === 'year' ? yearlyPrice : price;
445
457
 
446
458
  return {
@@ -457,24 +469,24 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
457
469
 
458
470
  const handleFeatureSubscribe = async (featureId: string) => {
459
471
  try {
460
- const selectedFeature = mockIndividualFeatures.find(feature => feature.id === featureId);
461
- if (!selectedFeature?.applicableApps.includes(currentAppPackage)) {
472
+ const featureToSubscribe = mockIndividualFeatures.find(feature => feature.id === featureId);
473
+ if (!featureToSubscribe?.applicableApps.includes(currentAppPackage)) {
462
474
  toast.error(`This feature is not available for the current app (${currentAppPackage})`);
463
475
  return;
464
476
  }
465
477
 
466
- if (selectedFeature.appScope === 'specific') {
467
- const hasExactMatch = selectedFeature.applicableApps.length === 1 &&
468
- selectedFeature.applicableApps[0] === currentAppPackage;
469
- if (!hasExactMatch && selectedFeature.applicableApps.length === 1) {
470
- const requiredApp = selectedFeature.applicableApps[0];
471
- toast.error(`${selectedFeature.name} is only available in the ${requiredApp} app`);
478
+ if (featureToSubscribe.appScope === 'specific') {
479
+ const hasExactMatch = featureToSubscribe.applicableApps.length === 1 &&
480
+ featureToSubscribe.applicableApps[0] === currentAppPackage;
481
+ if (!hasExactMatch && featureToSubscribe.applicableApps.length === 1) {
482
+ const requiredApp = featureToSubscribe.applicableApps[0];
483
+ toast.error(`${featureToSubscribe.name} is only available in the ${requiredApp} app`);
472
484
  return;
473
485
  }
474
486
  }
475
487
 
476
488
  setProcessingPayment(true);
477
- await new Promise(resolve => setTimeout(resolve, 1500));
489
+ await new Promise(resolve => setTimeout(resolve, FEATURE_DELAY_MS));
478
490
 
479
491
  setIndividualFeatures(prev =>
480
492
  prev.map(feature =>
@@ -526,37 +538,16 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
526
538
  [individualFeatures, pendingUnsubscribeFeatureId]
527
539
  );
528
540
 
529
- const renderHeader = () => {
530
- const getAppDisplayName = (packageName: string) => {
531
- const appNames: Record<string, string> = {
532
- 'mention': 'Mention',
533
- 'oxy-social': 'Oxy Social',
534
- 'oxy-workspace': 'Oxy Workspace',
535
- 'oxy-creator': 'Oxy Creator',
536
- 'oxy-analytics': 'Oxy Analytics',
537
- 'oxy-studio': 'Oxy Studio'
538
- };
539
- return appNames[packageName] || packageName;
541
+ const getAppDisplayName = (packageName: string) => {
542
+ const appNames: Record<string, string> = {
543
+ 'mention': 'Mention',
544
+ 'oxy-social': 'Oxy Social',
545
+ 'oxy-workspace': 'Oxy Workspace',
546
+ 'oxy-creator': 'Oxy Creator',
547
+ 'oxy-analytics': 'Oxy Analytics',
548
+ 'oxy-studio': 'Oxy Studio'
540
549
  };
541
-
542
- return (
543
- <View style={[styles.header, { borderBottomColor: borderColor }]}>
544
- <TouchableOpacity style={styles.backButton} onPress={goBack}>
545
- <Ionicons name="arrow-back" size={24} color={textColor} />
546
- </TouchableOpacity>
547
- <View style={styles.headerTitleContainer}>
548
- <Text style={[styles.headerTitle, { color: textColor }]}>{t('premium.title') || 'Oxy+ Subscriptions'}</Text>
549
- <Text style={[styles.currentAppText, { color: bloomTheme.colors.textSecondary }]}>
550
- {t('premium.forApp', { app: getAppDisplayName(currentAppPackage) }) || `for ${getAppDisplayName(currentAppPackage)}`}
551
- </Text>
552
- </View>
553
- {onClose && (
554
- <TouchableOpacity style={styles.closeButton} onPress={onClose}>
555
- <Ionicons name="close" size={24} color={textColor} />
556
- </TouchableOpacity>
557
- )}
558
- </View>
559
- );
550
+ return appNames[packageName] || packageName;
560
551
  };
561
552
 
562
553
  const renderCurrentSubscription = () => {
@@ -565,66 +556,72 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
565
556
  const currentPlan = getCurrentPlan();
566
557
  if (!currentPlan) return null;
567
558
 
568
- const statusColor =
569
- subscription.status === 'active' ? successColor :
570
- subscription.status === 'trialing' ? warningColor :
571
- dangerColor;
559
+ const statusChipColor =
560
+ subscription.status === 'active' ? 'success' :
561
+ subscription.status === 'trialing' ? 'warning' :
562
+ 'error';
572
563
 
573
564
  return (
574
- <View style={styles.section}>
575
- <Text style={[styles.sectionTitle, { color: textColor }]}>{t('premium.current.title') || 'Current Subscription'}</Text>
576
-
577
- <View style={[styles.currentSubscriptionCard, { backgroundColor: secondaryBackgroundColor, borderColor }]}>
578
- <View style={styles.subscriptionHeader}>
579
- <View>
580
- <Text style={[styles.planName, { color: textColor }]}>{currentPlan.name}</Text>
581
- <Text style={[styles.planPrice, { color: primaryColor }]}>
582
- ${currentPlan.price}/month
583
- </Text>
584
- </View>
585
- <View style={[styles.statusBadge, { backgroundColor: statusColor }]}>
586
- <Text style={styles.statusText}>
587
- {subscription.status.toUpperCase()}
565
+ <View className="mb-space-24">
566
+ <H5 className="text-text mb-space-12">
567
+ {t('premium.current.title') || 'Current Subscription'}
568
+ </H5>
569
+
570
+ <View className="bg-fill border border-border-image rounded-radius-20 p-space-20 shadow-s">
571
+ <View className="flex-row justify-between items-start mb-space-12">
572
+ <View className="flex-1 pr-space-12">
573
+ <H4 className="text-text" numberOfLines={1}>{currentPlan.name}</H4>
574
+ <Text className="text-text-secondary text-sm mt-space-2">
575
+ {`$${currentPlan.price}/month`}
588
576
  </Text>
589
577
  </View>
578
+ <Chip variant="soft" color={statusChipColor} size="small">
579
+ {subscription.status.toUpperCase()}
580
+ </Chip>
590
581
  </View>
591
582
 
592
- <Text style={[styles.subscriptionDetail, { color: bloomTheme.colors.textSecondary }]}>
583
+ <Text className="text-text-secondary text-sm mb-space-16">
593
584
  {t('premium.current.renewsOn', { date: new Date(subscription.currentPeriodEnd).toLocaleDateString() }) || `Renews on ${new Date(subscription.currentPeriodEnd).toLocaleDateString()}`}
594
585
  </Text>
595
586
 
596
587
  {subscription.cancelAtPeriodEnd && (
597
- <View style={styles.cancelNotice}>
598
- <Ionicons name="warning" size={16} color={warningColor} />
599
- <Text style={[styles.cancelText, { color: warningColor }]}>
588
+ <View className="flex-row items-center bg-fill-secondary rounded-radius-12 p-space-12 mb-space-16">
589
+ <Ionicons name="warning" size={16} color={colors.warning} />
590
+ <Text className="text-text-secondary text-sm ml-space-8 flex-1">
600
591
  {t('premium.current.willCancelOn', { date: new Date(subscription.currentPeriodEnd).toLocaleDateString() }) || `Subscription will cancel on ${new Date(subscription.currentPeriodEnd).toLocaleDateString()}`}
601
592
  </Text>
602
593
  </View>
603
594
  )}
604
595
 
605
- <View style={styles.subscriptionActions}>
596
+ <View className="flex-row gap-space-12">
606
597
  {subscription.cancelAtPeriodEnd ? (
607
- <TouchableOpacity
608
- style={[styles.actionButton, { backgroundColor: successColor }]}
598
+ <Button
599
+ variant="primary"
609
600
  onPress={handleReactivateSubscription}
601
+ className="flex-1"
602
+ accessibilityLabel={t('premium.actions.reactivate') || 'Reactivate'}
610
603
  >
611
- <Text style={styles.actionButtonText}>{t('premium.actions.reactivate') || 'Reactivate'}</Text>
612
- </TouchableOpacity>
604
+ {t('premium.actions.reactivate') || 'Reactivate'}
605
+ </Button>
613
606
  ) : (
614
- <TouchableOpacity
615
- style={[styles.actionButton, { backgroundColor: dangerColor }]}
607
+ <Button
608
+ variant="destructive"
616
609
  onPress={confirmCancelSubscription}
610
+ className="flex-1"
611
+ accessibilityLabel={t('premium.actions.cancelSubBtn') || 'Cancel Subscription'}
617
612
  >
618
- <Text style={styles.actionButtonText}>{t('premium.actions.cancelSubBtn') || 'Cancel Subscription'}</Text>
619
- </TouchableOpacity>
613
+ {t('premium.actions.cancelSubBtn') || 'Cancel Subscription'}
614
+ </Button>
620
615
  )}
621
616
 
622
- <TouchableOpacity
623
- style={[styles.actionButton, styles.secondaryButton, { borderColor }]}
624
-
617
+ <Button
618
+ variant="outline"
619
+ onPress={() => navigate?.('PaymentGateway')}
620
+ className="flex-1"
621
+ accessibilityLabel={t('premium.actions.manageBilling') || 'Manage Billing'}
625
622
  >
626
- <Text style={[styles.actionButtonText, { color: textColor }]}>{t('premium.actions.manageBilling') || 'Manage Billing'}</Text>
627
- </TouchableOpacity>
623
+ {t('premium.actions.manageBilling') || 'Manage Billing'}
624
+ </Button>
628
625
  </View>
629
626
  </View>
630
627
  </View>
@@ -632,49 +629,35 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
632
629
  };
633
630
 
634
631
  const renderBillingToggle = () => (
635
- <View style={styles.section}>
636
- <View style={styles.billingToggle}>
637
- <TouchableOpacity
638
- style={[
639
- styles.billingOption,
640
- billingInterval === 'month' && { backgroundColor: primaryColor }
641
- ]}
642
- onPress={() => setBillingInterval('month')}
643
- >
644
- <Text style={[
645
- styles.billingOptionText,
646
- { color: billingInterval === 'month' ? bloomTheme.colors.negativeForeground : textColor }
647
- ]}>
632
+ <View className="mb-space-24">
633
+ <SegmentedControl<BillingInterval>
634
+ label={t('premium.billing.label') || 'Billing period'}
635
+ type="tabs"
636
+ value={billingInterval}
637
+ onChange={setBillingInterval}
638
+ >
639
+ <SegmentedControlItem value={BILLING_MONTH}>
640
+ <SegmentedControlItemText>
648
641
  {t('premium.billing.monthly') || 'Monthly'}
649
- </Text>
650
- </TouchableOpacity>
651
-
652
- <TouchableOpacity
653
- style={[
654
- styles.billingOption,
655
- billingInterval === 'year' && { backgroundColor: primaryColor }
656
- ]}
657
- onPress={() => setBillingInterval('year')}
658
- >
659
- <Text style={[
660
- styles.billingOptionText,
661
- { color: billingInterval === 'year' ? bloomTheme.colors.negativeForeground : textColor }
662
- ]}>
642
+ </SegmentedControlItemText>
643
+ </SegmentedControlItem>
644
+ <SegmentedControlItem value={BILLING_YEAR}>
645
+ <SegmentedControlItemText>
663
646
  {t('premium.billing.yearly') || 'Yearly'}
664
- </Text>
665
- </TouchableOpacity>
666
- </View>
647
+ </SegmentedControlItemText>
648
+ </SegmentedControlItem>
649
+ </SegmentedControl>
667
650
 
668
651
  {billingInterval === 'year' && (
669
- <Text style={[styles.savingsText, { color: successColor }]}>
670
- {t('premium.billing.saveYearly') || '💰 Save 20% with yearly billing'}
652
+ <Text className="text-text-secondary text-sm text-center mt-space-12 font-medium">
653
+ {t('premium.billing.saveYearly') || 'Save 20% with yearly billing'}
671
654
  </Text>
672
655
  )}
673
656
  </View>
674
657
  );
675
658
 
676
659
  const renderPlanCard = (plan: SubscriptionPlan) => {
677
- const pricing = formatPrice(plan.price, plan.currency, plan.interval);
660
+ const pricing = formatPrice(plan.price, plan.interval);
678
661
  const isSelected = selectedPlan === plan.id;
679
662
  const isCurrentPlan = subscription?.planId === plan.id;
680
663
  const isAppSpecific = plan.appScope === 'specific' && plan.applicableApps.length === 1;
@@ -683,11 +666,12 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
683
666
  const getAppScopeText = () => {
684
667
  if (plan.appScope === 'ecosystem') {
685
668
  return t('premium.plan.scope.allApps') || 'Works across all Oxy apps';
686
- }if (isAppSpecific) {
669
+ }
670
+ if (isAppSpecific) {
687
671
  const appName = plan.applicableApps[0];
688
672
  return t('premium.plan.scope.exclusive', { app: appName }) || `Exclusive to ${appName} app`;
689
673
  }
690
- return t('premium.plan.scope.availableIn', { apps: plan.applicableApps.join(', ') }) || `Available in: ${plan.applicableApps.join(', ')}`;
674
+ return t('premium.plan.scope.availableIn', { apps: plan.applicableApps.join(', ') }) || `Available in: ${plan.applicableApps.join(', ')}`;
691
675
  };
692
676
 
693
677
  const getAvailabilityStatus = () => {
@@ -706,152 +690,139 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
706
690
  return (
707
691
  <View
708
692
  key={plan.id}
709
- style={[
710
- styles.planCard,
711
- { backgroundColor: secondaryBackgroundColor, borderColor },
712
- isSelected && { borderColor: primaryColor, borderWidth: 2 },
713
- plan.isPopular && styles.popularPlan,
714
- !availability.available && { opacity: 0.6 }
715
- ]}
693
+ className={`bg-fill border border-border-image rounded-radius-20 p-space-20 mb-space-16 shadow-s ${!availability.available ? 'opacity-60' : ''}`}
694
+ style={
695
+ isSelected || plan.isPopular
696
+ ? { borderColor: colors.primary, borderWidth: 2 }
697
+ : undefined
698
+ }
716
699
  >
717
- {plan.isPopular && (
718
- <View style={[styles.popularBadge, { backgroundColor: primaryColor }]}>
719
- <Text style={styles.popularText}>MOST POPULAR</Text>
720
- </View>
721
- )}
722
-
723
- {isAppSpecific && (
724
- <View style={[styles.appSpecificBadge, {
725
- backgroundColor: isAvailableForCurrentApp ? successColor : warningColor
726
- }]}>
727
- <Text style={styles.appSpecificText}>
728
- {isAvailableForCurrentApp ? (t('premium.plan.badge.appExclusive') || 'App Exclusive') : (t('premium.plan.badge.notAvailable') || 'Not Available')}
729
- </Text>
730
- </View>
731
- )}
700
+ <View className="flex-row flex-wrap gap-space-8 mb-space-12">
701
+ {plan.isPopular && (
702
+ <Chip variant="solid" color="primary" size="small">
703
+ {t('premium.plan.badge.mostPopular') || 'Most Popular'}
704
+ </Chip>
705
+ )}
706
+ {isAppSpecific && (
707
+ <Chip
708
+ variant="soft"
709
+ color={isAvailableForCurrentApp ? 'success' : 'warning'}
710
+ size="small"
711
+ >
712
+ {isAvailableForCurrentApp
713
+ ? (t('premium.plan.badge.appExclusive') || 'App Exclusive')
714
+ : (t('premium.plan.badge.notAvailable') || 'Not Available')}
715
+ </Chip>
716
+ )}
717
+ </View>
732
718
 
733
- <View style={styles.planHeader}>
734
- <Text style={[styles.planName, { color: textColor }]}>{plan.name}</Text>
735
- <Text style={[styles.planDescription, { color: bloomTheme.colors.textSecondary }]}>
719
+ <View className="mb-space-16">
720
+ <H4 className="text-text mb-space-4">{plan.name}</H4>
721
+ <Text className="text-text-secondary text-sm">
736
722
  {plan.description}
737
723
  </Text>
738
- <Text style={[styles.planAppScope, { color: bloomTheme.colors.textTertiary }]}>
724
+ <Text className="text-text-tertiary text-xs mt-space-4 italic">
739
725
  {getAppScopeText()}
740
726
  </Text>
741
727
  {!availability.available && (
742
- <Text style={[styles.planRestrictionText, { color: dangerColor }]}>
728
+ <Text className="text-xs mt-space-4 font-medium" style={{ color: colors.error }}>
743
729
  {availability.reason}
744
730
  </Text>
745
731
  )}
746
732
  </View>
747
733
 
748
- <View style={styles.planPricing}>
749
- <Text style={[styles.planPrice, { color: textColor }]}>
750
- {pricing.formatted}
751
- </Text>
752
- <Text style={[styles.planInterval, { color: bloomTheme.colors.textSecondary }]}>
734
+ <View className="flex-row items-baseline mb-space-20">
735
+ <H2 className="text-text">{pricing.formatted}</H2>
736
+ <Text className="text-text-secondary text-sm ml-space-4">
753
737
  {t('premium.plan.perInterval', { interval: pricing.interval }) || `per ${pricing.interval}`}
754
738
  </Text>
755
739
  </View>
756
740
 
757
- <View style={styles.planFeatures}>
741
+ <BenefitList className="mb-space-24">
758
742
  {plan.features.map((feature, index) => (
759
- <View key={index} style={styles.featureItem}>
760
- <Ionicons name="checkmark" size={16} color={successColor} />
761
- <Text style={[styles.featureText, { color: textColor }]}>{feature}</Text>
762
- </View>
743
+ <BenefitRow
744
+ key={index}
745
+ icon={<Ionicons name="checkmark" size={18} color={colors.success} />}
746
+ label={feature}
747
+ />
763
748
  ))}
764
- </View>
749
+ </BenefitList>
765
750
 
766
751
  {isCurrentPlan ? (
767
- <View style={[styles.currentPlanButton, { backgroundColor: successColor }]}>
768
- <Text style={styles.currentPlanText}>{t('premium.plan.current') || 'Current Plan'}</Text>
769
- </View>
752
+ <Button
753
+ variant="secondary"
754
+ disabled
755
+ icon={<Ionicons name="checkmark-circle" size={18} color={colors.success} />}
756
+ accessibilityLabel={t('premium.plan.current') || 'Current Plan'}
757
+ className="w-full"
758
+ >
759
+ {t('premium.plan.current') || 'Current Plan'}
760
+ </Button>
770
761
  ) : !availability.available ? (
771
- <View style={[styles.unavailablePlanButton, { backgroundColor: bloomTheme.colors.border }]}>
772
- <Text style={[styles.unavailablePlanText, { color: bloomTheme.colors.textTertiary }]}>
773
- {t('premium.plan.notAvailableInApp') || 'Not Available in Current App'}
774
- </Text>
775
- </View>
762
+ <Button
763
+ variant="secondary"
764
+ disabled
765
+ accessibilityLabel={t('premium.plan.notAvailableInApp') || 'Not Available in Current App'}
766
+ className="w-full"
767
+ >
768
+ {t('premium.plan.notAvailableInApp') || 'Not Available in Current App'}
769
+ </Button>
776
770
  ) : (
777
- <TouchableOpacity
778
- style={[
779
- styles.selectPlanButton,
780
- { backgroundColor: plan.isPopular ? primaryColor : borderColor }
781
- ]}
771
+ <Button
772
+ variant={plan.isPopular ? 'primary' : 'secondary'}
782
773
  onPress={() => handleSubscribe(plan.id)}
783
774
  disabled={processingPayment}
775
+ loading={processingPayment && isSelected}
776
+ accessibilityLabel={t('premium.actions.subscribeTo', { name: plan.name }) || `Subscribe to ${plan.name}`}
777
+ className="w-full"
784
778
  >
785
- {processingPayment ? (
786
- <ActivityIndicator color={bloomTheme.colors.negativeForeground} size="small" />
787
- ) : (
788
- <Text style={[
789
- styles.selectPlanText,
790
- { color: plan.isPopular ? bloomTheme.colors.negativeForeground : textColor }
791
- ]}>
792
- {t('premium.actions.subscribeTo', { name: plan.name }) || `Subscribe to ${plan.name}`}
793
- </Text>
794
- )}
795
- </TouchableOpacity>
779
+ {t('premium.actions.subscribeTo', { name: plan.name }) || `Subscribe to ${plan.name}`}
780
+ </Button>
796
781
  )}
797
782
  </View>
798
783
  );
799
784
  };
800
785
 
801
786
  const renderTabNavigation = () => (
802
- <View style={styles.section}>
803
- <View style={[styles.tabContainer, { borderBottomColor: borderColor }]}>
804
- <TouchableOpacity
805
- style={[
806
- styles.tab,
807
- activeTab === 'plans' && { borderBottomColor: primaryColor, borderBottomWidth: 2 }
808
- ]}
809
- onPress={() => setActiveTab('plans')}
810
- >
811
- <Text style={[
812
- styles.tabText,
813
- { color: activeTab === 'plans' ? primaryColor : textColor }
814
- ]}>
787
+ <View className="mb-space-24">
788
+ <SegmentedControl<ActiveTab>
789
+ label={t('premium.tabs.label') || 'Subscription type'}
790
+ type="tabs"
791
+ value={activeTab}
792
+ onChange={setActiveTab}
793
+ >
794
+ <SegmentedControlItem value={TAB_PLANS}>
795
+ <SegmentedControlItemText>
815
796
  {t('premium.tabs.plans') || 'Full Plans'}
816
- </Text>
817
- </TouchableOpacity>
818
-
819
- <TouchableOpacity
820
- style={[
821
- styles.tab,
822
- activeTab === 'features' && { borderBottomColor: primaryColor, borderBottomWidth: 2 }
823
- ]}
824
- onPress={() => setActiveTab('features')}
825
- >
826
- <Text style={[
827
- styles.tabText,
828
- { color: activeTab === 'features' ? primaryColor : textColor }
829
- ]}>
797
+ </SegmentedControlItemText>
798
+ </SegmentedControlItem>
799
+ <SegmentedControlItem value={TAB_FEATURES}>
800
+ <SegmentedControlItemText>
830
801
  {t('premium.tabs.features') || 'Individual Features'}
831
- </Text>
832
- </TouchableOpacity>
833
- </View>
802
+ </SegmentedControlItemText>
803
+ </SegmentedControlItem>
804
+ </SegmentedControl>
834
805
  </View>
835
806
  );
836
807
 
837
808
  const renderFeatureCard = (feature: IndividualFeature) => {
838
- const pricing = formatPrice(feature.price, feature.currency, feature.interval);
809
+ const pricing = formatPrice(feature.price, feature.interval);
839
810
  const isSubscribed = feature.isSubscribed;
840
811
  const isIncludedInCurrentPlan = feature.isIncludedInCurrentPlan;
841
812
  const canPurchase = feature.canBePurchasedSeparately && !isIncludedInCurrentPlan;
842
813
 
843
814
  const getCategoryColor = (category: string) => {
844
815
  switch (category) {
845
- case 'analytics': return bloomTheme.colors.warning;
846
- case 'customization': return bloomTheme.colors.secondary;
847
- case 'content': return bloomTheme.colors.success;
848
- case 'networking': return bloomTheme.colors.info;
849
- case 'productivity': return bloomTheme.colors.error;
850
- default: return primaryColor;
816
+ case 'analytics': return colors.warning;
817
+ case 'customization': return colors.secondary;
818
+ case 'content': return colors.success;
819
+ case 'networking': return colors.info;
820
+ case 'productivity': return colors.error;
821
+ default: return colors.primary;
851
822
  }
852
823
  };
853
824
 
854
- const getCategoryIcon = (category: string) => {
825
+ const getCategoryIcon = (category: string): IoniconName => {
855
826
  switch (category) {
856
827
  case 'analytics': return 'analytics';
857
828
  case 'customization': return 'color-palette';
@@ -866,126 +837,141 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
866
837
  if (feature.appScope === 'ecosystem') {
867
838
  return t('premium.feature.scope.allApps');
868
839
  }
869
- return t('premium.feature.scope.availableIn', { apps: feature.applicableApps.join(', ') }) || `Available in: ${feature.applicableApps.join(', ')}`;
840
+ return t('premium.feature.scope.availableIn', { apps: feature.applicableApps.join(', ') }) || `Available in: ${feature.applicableApps.join(', ')}`;
870
841
  };
871
842
 
872
843
  return (
873
844
  <View
874
845
  key={feature.id}
875
- style={[
876
- styles.featureCard,
877
- { backgroundColor: secondaryBackgroundColor, borderColor },
878
- isSubscribed && { borderColor: successColor, borderWidth: 2 },
879
- isIncludedInCurrentPlan && { borderColor: primaryColor, borderWidth: 2 }
880
- ]}
846
+ className="bg-fill border border-border-image rounded-radius-12 p-space-16 mb-space-12 shadow-s"
847
+ style={
848
+ isIncludedInCurrentPlan
849
+ ? { borderColor: colors.primary, borderWidth: 2 }
850
+ : isSubscribed
851
+ ? { borderColor: colors.success, borderWidth: 2 }
852
+ : undefined
853
+ }
881
854
  >
882
- <View style={styles.featureHeader}>
883
- <View style={styles.featureIconContainer}>
855
+ <View className="flex-row items-start mb-space-12">
856
+ <View
857
+ className="bg-fill-secondary rounded-radius-max items-center justify-center mr-space-12"
858
+ style={{ width: 40, height: 40 }}
859
+ >
884
860
  <Ionicons
885
- name={getCategoryIcon(feature.category) as React.ComponentProps<typeof Ionicons>['name']}
861
+ name={getCategoryIcon(feature.category)}
886
862
  size={24}
887
863
  color={getCategoryColor(feature.category)}
888
864
  />
889
865
  </View>
890
- <View style={styles.featureInfo}>
891
- <View style={styles.featureNameRow}>
892
- <Text style={[styles.featureName, { color: textColor }]}>{feature.name}</Text>
866
+ <View className="flex-1">
867
+ <View className="flex-row items-center justify-between mb-space-4">
868
+ <H5 className="text-text flex-1 pr-space-8" numberOfLines={1}>{feature.name}</H5>
893
869
  {isIncludedInCurrentPlan && (
894
- <View style={[styles.includedBadge, { backgroundColor: primaryColor }]}>
895
- <Text style={styles.includedBadgeText}>Included</Text>
896
- </View>
870
+ <Chip variant="solid" color="primary" size="small">
871
+ {t('premium.feature.included') || 'Included'}
872
+ </Chip>
897
873
  )}
898
874
  </View>
899
- <Text style={[styles.featureDescription, { color: bloomTheme.colors.textSecondary }]}>
875
+ <Text className="text-text-secondary text-sm">
900
876
  {feature.description}
901
877
  </Text>
902
- <Text style={[styles.appScopeText, { color: bloomTheme.colors.textTertiary }]}>
878
+ <Text className="text-text-tertiary text-xs mt-space-4 italic">
903
879
  {getAppScopeText()}
904
880
  </Text>
905
881
  </View>
906
882
  </View>
907
883
 
908
884
  {!isIncludedInCurrentPlan && (
909
- <View style={styles.featurePricing}>
910
- <Text style={[styles.featurePrice, { color: textColor }]}>
911
- {pricing.formatted}
912
- </Text>
913
- <Text style={[styles.featureInterval, { color: bloomTheme.colors.textSecondary }]}>
885
+ <View className="items-center mb-space-16">
886
+ <H4 className="text-text">{pricing.formatted}</H4>
887
+ <Text className="text-text-secondary text-sm mt-space-2">
914
888
  {t('premium.plan.perInterval', { interval: pricing.interval }) || `per ${pricing.interval}`}
915
889
  </Text>
916
890
  </View>
917
891
  )}
918
892
 
919
893
  {isIncludedInCurrentPlan ? (
920
- <View style={[styles.includedInPlanButton, { backgroundColor: primaryColor }]}>
921
- <Ionicons name="checkmark-circle" size={16} color={bloomTheme.colors.negativeForeground} />
922
- <Text style={styles.includedInPlanText}>{t('premium.feature.includedInPlan') || 'Included in your plan'}</Text>
923
- </View>
894
+ <Button
895
+ variant="primary"
896
+ disabled
897
+ icon={<Ionicons name="checkmark-circle" size={16} color={colors.primaryForeground} />}
898
+ accessibilityLabel={t('premium.feature.includedInPlan') || 'Included in your plan'}
899
+ className="w-full"
900
+ >
901
+ {t('premium.feature.includedInPlan') || 'Included in your plan'}
902
+ </Button>
924
903
  ) : isSubscribed ? (
925
- <View style={styles.featureActions}>
926
- <View style={[styles.subscribedButton, { backgroundColor: successColor }]}>
927
- <Ionicons name="checkmark" size={16} color={bloomTheme.colors.negativeForeground} />
928
- <Text style={styles.subscribedText}>{t('premium.feature.subscribed') || 'Subscribed'}</Text>
929
- </View>
930
- <TouchableOpacity
931
- style={[styles.unsubscribeButton, { borderColor: dangerColor }]}
904
+ <View className="flex-row gap-space-8">
905
+ <Button
906
+ variant="secondary"
907
+ disabled
908
+ icon={<Ionicons name="checkmark" size={16} color={colors.success} />}
909
+ accessibilityLabel={t('premium.feature.subscribed') || 'Subscribed'}
910
+ className="flex-1"
911
+ >
912
+ {t('premium.feature.subscribed') || 'Subscribed'}
913
+ </Button>
914
+ <Button
915
+ variant="outline"
932
916
  onPress={() => confirmFeatureUnsubscribe(feature.id)}
917
+ accessibilityLabel={t('premium.actions.unsubscribe') || 'Unsubscribe'}
918
+ className="flex-1"
933
919
  >
934
- <Text style={[styles.unsubscribeText, { color: dangerColor }]}>{t('premium.actions.unsubscribe') || 'Unsubscribe'}</Text>
935
- </TouchableOpacity>
920
+ {t('premium.actions.unsubscribe') || 'Unsubscribe'}
921
+ </Button>
936
922
  </View>
937
923
  ) : canPurchase ? (
938
- <TouchableOpacity
939
- style={[styles.subscribeFeatureButton, { backgroundColor: primaryColor }]}
924
+ <Button
925
+ variant="primary"
940
926
  onPress={() => handleFeatureSubscribe(feature.id)}
941
927
  disabled={processingPayment}
928
+ loading={processingPayment}
929
+ accessibilityLabel={t('premium.actions.subscribe') || 'Subscribe'}
930
+ className="w-full"
942
931
  >
943
- {processingPayment ? (
944
- <ActivityIndicator color={bloomTheme.colors.negativeForeground} size="small" />
945
- ) : (
946
- <Text style={styles.subscribeFeatureText}>{t('premium.actions.subscribe') || 'Subscribe'}</Text>
947
- )}
948
- </TouchableOpacity>
932
+ {t('premium.actions.subscribe') || 'Subscribe'}
933
+ </Button>
949
934
  ) : (
950
- <View style={[styles.unavailableButton, { backgroundColor: bloomTheme.colors.border }]}>
951
- <Text style={[styles.unavailableText, { color: bloomTheme.colors.textTertiary }]}>
952
- Only available in subscription plans
953
- </Text>
954
- </View>
935
+ <Button
936
+ variant="secondary"
937
+ disabled
938
+ accessibilityLabel={t('premium.feature.plansOnly') || 'Only available in subscription plans'}
939
+ className="w-full"
940
+ >
941
+ {t('premium.feature.plansOnly') || 'Only available in subscription plans'}
942
+ </Button>
955
943
  )}
956
944
  </View>
957
945
  );
958
946
  };
959
947
 
960
- const renderIndividualFeatures = () => {
961
- const categories = ['analytics', 'customization', 'content', 'networking', 'productivity'];
962
-
963
- return (
964
- <View style={styles.section}>
965
- <Text style={[styles.sectionTitle, { color: textColor }]}>Individual Features</Text>
966
- <Text style={[styles.sectionSubtitle, { color: bloomTheme.colors.textSecondary }]}>
967
- Subscribe to specific features you need. Some features are included in subscription plans.
968
- </Text>
969
-
970
- {categories.map(category => {
971
- const categoryFeatures = individualFeatures.filter(f => f.category === category);
972
- if (categoryFeatures.length === 0) return null;
973
-
974
- return (
975
- <View key={category} style={styles.categorySection}>
976
- <Text style={[styles.categoryTitle, { color: textColor }]}>
977
- {category.charAt(0).toUpperCase() + category.slice(1)}
978
- </Text>
979
- {categoryFeatures.map(renderFeatureCard)}
980
- </View>
981
- );
982
- })}
983
- </View>
984
- );
985
- };
948
+ const renderIndividualFeatures = () => (
949
+ <View className="mb-space-24">
950
+ <H4 className="text-text mb-space-8">
951
+ {t('premium.features.title') || 'Individual Features'}
952
+ </H4>
953
+ <Text className="text-text-secondary text-base mb-space-16">
954
+ {t('premium.features.subtitle') || 'Subscribe to specific features you need. Some features are included in subscription plans.'}
955
+ </Text>
956
+
957
+ {FEATURE_CATEGORIES.map(category => {
958
+ const categoryFeatures = individualFeatures.filter(f => f.category === category);
959
+ if (categoryFeatures.length === 0) return null;
960
+
961
+ return (
962
+ <View key={category} className="mb-space-24">
963
+ <H5 className="text-text mb-space-12">
964
+ {category.charAt(0).toUpperCase() + category.slice(1)}
965
+ </H5>
966
+ {categoryFeatures.map(renderFeatureCard)}
967
+ </View>
968
+ );
969
+ })}
970
+ </View>
971
+ );
986
972
 
987
- // Add this for testing different app contexts (remove in production)
988
- const [showAppSwitcher, setShowAppSwitcher] = useState(__DEV__); // Only show in development
973
+ // Show different app contexts for testing (development only).
974
+ const [showAppSwitcher] = useState(__DEV__);
989
975
 
990
976
  const renderAppSwitcher = () => {
991
977
  if (!showAppSwitcher) return null;
@@ -993,33 +979,21 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
993
979
  const testApps = ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator'];
994
980
 
995
981
  return (
996
- <View style={[styles.appSwitcher, { backgroundColor: bloomTheme.colors.backgroundSecondary, borderColor }]}>
997
- <Text style={[styles.appSwitcherTitle, { color: textColor }]}>
998
- 🧪 Test App Context (Dev Only)
982
+ <View className="bg-fill-secondary border border-border-image rounded-radius-12 p-space-16 mb-space-24">
983
+ <Text className="text-text-secondary text-sm font-medium mb-space-12">
984
+ {t('premium.dev.appContext') || 'Test App Context (Dev Only)'}
999
985
  </Text>
1000
986
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
1001
- <View style={styles.appSwitcherButtons}>
987
+ <View className="flex-row gap-space-8">
1002
988
  {testApps.map(app => (
1003
- <TouchableOpacity
989
+ <Chip
1004
990
  key={app}
1005
- style={[
1006
- styles.appSwitcherButton,
1007
- {
1008
- backgroundColor: currentAppPackage === app ? primaryColor : 'transparent',
1009
- borderColor: primaryColor,
1010
- }
1011
- ]}
1012
- onPress={() => {
1013
- setCurrentAppPackage(app);
1014
- }}
991
+ variant={currentAppPackage === app ? 'solid' : 'outlined'}
992
+ color="primary"
993
+ onPress={() => setCurrentAppPackage(app)}
1015
994
  >
1016
- <Text style={[
1017
- styles.appSwitcherButtonText,
1018
- { color: currentAppPackage === app ? bloomTheme.colors.negativeForeground : textColor }
1019
- ]}>
1020
- {app}
1021
- </Text>
1022
- </TouchableOpacity>
995
+ {app}
996
+ </Chip>
1023
997
  ))}
1024
998
  </View>
1025
999
  </ScrollView>
@@ -1029,85 +1003,116 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
1029
1003
 
1030
1004
  if (loading) {
1031
1005
  return (
1032
- <View style={[styles.container, { backgroundColor, justifyContent: 'center' }]}>
1033
- <ActivityIndicator size="large" color={primaryColor} />
1034
- <Text style={[styles.loadingText, { color: textColor }]}>{t('premium.loading') || 'Loading subscription plans...'}</Text>
1006
+ <View className="flex-1 bg-bg">
1007
+ <Header
1008
+ title={t('premium.title') || 'Oxy+ Subscriptions'}
1009
+ subtitle={t('premium.forApp', { app: getAppDisplayName(currentAppPackage) }) || `for ${getAppDisplayName(currentAppPackage)}`}
1010
+ onBack={goBack || onClose}
1011
+ onClose={onClose}
1012
+ showCloseButton={!!onClose}
1013
+ elevation="subtle"
1014
+ />
1015
+ <View className="flex-1 items-center justify-center px-screen-margin">
1016
+ <ActivityIndicator size="large" color={colors.primary} />
1017
+ <Text className="text-text-secondary text-base text-center mt-space-16">
1018
+ {t('premium.loading') || 'Loading subscription plans...'}
1019
+ </Text>
1020
+ </View>
1035
1021
  </View>
1036
1022
  );
1037
1023
  }
1038
1024
 
1039
1025
  return (
1040
- <View style={[styles.container, { backgroundColor }]}>
1041
- {renderHeader()}
1042
- {renderAppSwitcher()}
1043
-
1044
- <ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
1045
- {subscription && renderCurrentSubscription()}
1046
-
1047
- {!subscription && (
1048
- <View style={styles.section}>
1049
- <Text style={[styles.sectionTitle, { color: textColor }]}>{t('premium.choosePlan') || 'Choose Your Plan'}</Text>
1050
- <Text style={[styles.sectionSubtitle, { color: bloomTheme.colors.textSecondary }]}>
1051
- {t('premium.choosePlanSubtitle') || 'Unlock premium features and take your experience to the next level'}
1052
- </Text>
1053
- </View>
1054
- )}
1055
-
1056
- {!subscription && renderTabNavigation()}
1026
+ <View className="flex-1 bg-bg">
1027
+ <Header
1028
+ title={t('premium.title') || 'Oxy+ Subscriptions'}
1029
+ subtitle={t('premium.forApp', { app: getAppDisplayName(currentAppPackage) }) || `for ${getAppDisplayName(currentAppPackage)}`}
1030
+ onBack={goBack || onClose}
1031
+ onClose={onClose}
1032
+ showCloseButton={!!onClose}
1033
+ elevation="subtle"
1034
+ />
1057
1035
 
1058
- {!subscription && activeTab === 'plans' && renderBillingToggle()}
1036
+ <ScrollView
1037
+ className="flex-1"
1038
+ contentContainerClassName="px-screen-margin pb-space-32"
1039
+ showsVerticalScrollIndicator={false}
1040
+ >
1041
+ <View className="pt-space-20">
1042
+ {renderAppSwitcher()}
1043
+
1044
+ {subscription && renderCurrentSubscription()}
1045
+
1046
+ {!subscription && (
1047
+ <View className="mb-space-24">
1048
+ <H2 className="text-text mb-space-8">
1049
+ {t('premium.choosePlan') || 'Choose Your Plan'}
1050
+ </H2>
1051
+ <Text className="text-text-secondary text-base">
1052
+ {t('premium.choosePlanSubtitle') || 'Unlock premium features and take your experience to the next level'}
1053
+ </Text>
1054
+ </View>
1055
+ )}
1059
1056
 
1060
- {activeTab === 'plans' ? (
1061
- <View style={styles.section}>
1062
- {!subscription && (
1063
- <Text style={[styles.sectionTitle, { color: textColor }]}>{t('premium.availablePlans') || 'Available Plans'}</Text>
1064
- )}
1057
+ {!subscription && renderTabNavigation()}
1065
1058
 
1066
- {plans.map(renderPlanCard)}
1067
- </View>
1068
- ) : (
1069
- renderIndividualFeatures()
1070
- )}
1059
+ {!subscription && activeTab === TAB_PLANS && renderBillingToggle()}
1071
1060
 
1072
- {/* Features Comparison */}
1073
- <View style={styles.section}>
1074
- <Text style={[styles.sectionTitle, { color: textColor }]}>{t('premium.why') || 'Why Go Premium?'}</Text>
1075
-
1076
- <View style={[styles.benefitsCard, { backgroundColor: secondaryBackgroundColor, borderColor }]}>
1077
- <View style={styles.benefitItem}>
1078
- <Ionicons name="flash" size={24} color={primaryColor} />
1079
- <View style={styles.benefitContent}>
1080
- <Text style={[styles.benefitTitle, { color: textColor }]}>{t('premium.benefits.performance.title') || 'Enhanced Performance'}</Text>
1081
- <Text style={[styles.benefitDescription, { color: bloomTheme.colors.textSecondary }]}>
1082
- {t('premium.benefits.performance.desc') || 'Faster processing and priority access to our servers'}
1083
- </Text>
1084
- </View>
1085
- </View>
1061
+ {activeTab === TAB_PLANS ? (
1062
+ <View className="mb-space-24">
1063
+ {!subscription && (
1064
+ <H4 className="text-text mb-space-12">
1065
+ {t('premium.availablePlans') || 'Available Plans'}
1066
+ </H4>
1067
+ )}
1086
1068
 
1087
- <View style={styles.benefitItem}>
1088
- <Ionicons name="shield-checkmark" size={24} color={successColor} />
1089
- <View style={styles.benefitContent}>
1090
- <Text style={[styles.benefitTitle, { color: textColor }]}>{t('premium.benefits.security.title') || 'Advanced Security'}</Text>
1091
- <Text style={[styles.benefitDescription, { color: bloomTheme.colors.textSecondary }]}>
1092
- {t('premium.benefits.security.desc') || 'Enhanced encryption and security features'}
1093
- </Text>
1094
- </View>
1069
+ {plans.map(renderPlanCard)}
1095
1070
  </View>
1071
+ ) : (
1072
+ renderIndividualFeatures()
1073
+ )}
1096
1074
 
1097
- <View style={styles.benefitItem}>
1098
- <Ionicons name="headset" size={24} color={warningColor} />
1099
- <View style={styles.benefitContent}>
1100
- <Text style={[styles.benefitTitle, { color: textColor }]}>{t('premium.benefits.support.title') || 'Priority Support'}</Text>
1101
- <Text style={[styles.benefitDescription, { color: bloomTheme.colors.textSecondary }]}>
1102
- {t('premium.benefits.support.desc') || 'Get help faster with our premium support team'}
1103
- </Text>
1104
- </View>
1105
- </View>
1075
+ {/* Why go premium */}
1076
+ <View className="mb-space-24">
1077
+ <H4 className="text-text mb-space-12">
1078
+ {t('premium.why') || 'Why Go Premium?'}
1079
+ </H4>
1080
+
1081
+ <BenefitList>
1082
+ {([
1083
+ {
1084
+ icon: 'flash' as IoniconName,
1085
+ color: colors.primary,
1086
+ title: t('premium.benefits.performance.title') || 'Enhanced Performance',
1087
+ desc: t('premium.benefits.performance.desc') || 'Faster processing and priority access to our servers',
1088
+ },
1089
+ {
1090
+ icon: 'shield-checkmark' as IoniconName,
1091
+ color: colors.success,
1092
+ title: t('premium.benefits.security.title') || 'Advanced Security',
1093
+ desc: t('premium.benefits.security.desc') || 'Enhanced encryption and security features',
1094
+ },
1095
+ {
1096
+ icon: 'headset' as IoniconName,
1097
+ color: colors.warning,
1098
+ title: t('premium.benefits.support.title') || 'Priority Support',
1099
+ desc: t('premium.benefits.support.desc') || 'Get help faster with our premium support team',
1100
+ },
1101
+ ]).map((benefit) => (
1102
+ <BenefitRow
1103
+ key={benefit.title}
1104
+ icon={<Ionicons name={benefit.icon} size={18} color={benefit.color} />}
1105
+ accessibilityLabel={`${benefit.title}. ${benefit.desc}`}
1106
+ >
1107
+ <Text className="text-text font-medium text-sm">{benefit.title}</Text>
1108
+ {`\n${benefit.desc}`}
1109
+ </BenefitRow>
1110
+ ))}
1111
+ </BenefitList>
1106
1112
  </View>
1107
1113
  </View>
1108
-
1109
- <View style={styles.bottomSpacing} />
1110
1114
  </ScrollView>
1115
+
1111
1116
  <Dialog
1112
1117
  control={cancelSubscriptionDialog}
1113
1118
  title={t('premium.confirms.cancelSubTitle') || 'Cancel Subscription'}
@@ -1130,462 +1135,4 @@ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
1130
1135
  );
1131
1136
  };
1132
1137
 
1133
- const styles = StyleSheet.create({
1134
- container: {
1135
- flex: 1,
1136
- },
1137
- header: {
1138
- flexDirection: 'row',
1139
- alignItems: 'center',
1140
- justifyContent: 'space-between',
1141
- paddingHorizontal: 20,
1142
- paddingTop: 20,
1143
- paddingBottom: 16,
1144
- borderBottomWidth: 1,
1145
- },
1146
- backButton: {
1147
- padding: 8,
1148
- },
1149
- headerTitle: {
1150
- fontSize: 20,
1151
- fontWeight: '600',
1152
- },
1153
- headerTitleContainer: {
1154
- flex: 1,
1155
- alignItems: 'center',
1156
- },
1157
- currentAppText: {
1158
- fontSize: 14,
1159
- marginTop: 2,
1160
- fontStyle: 'italic',
1161
- },
1162
- closeButton: {
1163
- padding: 8,
1164
- },
1165
- content: {
1166
- flex: 1,
1167
- },
1168
- section: {
1169
- padding: 20,
1170
- },
1171
- sectionTitle: {
1172
- fontSize: 24,
1173
- fontWeight: 'bold',
1174
- marginBottom: 8,
1175
- },
1176
- sectionSubtitle: {
1177
- fontSize: 16,
1178
- lineHeight: 22,
1179
- },
1180
- loadingText: {
1181
- fontSize: 16,
1182
- textAlign: 'center',
1183
- marginTop: 16,
1184
- },
1185
- currentSubscriptionCard: {
1186
- borderRadius: 16,
1187
- padding: 20,
1188
- borderWidth: 1,
1189
- },
1190
- subscriptionHeader: {
1191
- flexDirection: 'row',
1192
- justifyContent: 'space-between',
1193
- alignItems: 'flex-start',
1194
- marginBottom: 12,
1195
- },
1196
- planName: {
1197
- fontSize: 20,
1198
- fontWeight: 'bold',
1199
- marginBottom: 4,
1200
- },
1201
- planPrice: {
1202
- fontSize: 16,
1203
- fontWeight: '600',
1204
- },
1205
- statusBadge: {
1206
- paddingHorizontal: 12,
1207
- paddingVertical: 4,
1208
- borderRadius: 12,
1209
- },
1210
- statusText: {
1211
- color: '#FFFFFF',
1212
- fontSize: 12,
1213
- fontWeight: '600',
1214
- },
1215
- subscriptionDetail: {
1216
- fontSize: 14,
1217
- marginBottom: 16,
1218
- },
1219
- cancelNotice: {
1220
- flexDirection: 'row',
1221
- alignItems: 'center',
1222
- padding: 12,
1223
- backgroundColor: 'rgba(255, 149, 0, 0.1)',
1224
- borderRadius: 8,
1225
- marginBottom: 16,
1226
- },
1227
- cancelText: {
1228
- fontSize: 14,
1229
- marginLeft: 8,
1230
- flex: 1,
1231
- },
1232
- subscriptionActions: {
1233
- flexDirection: 'row',
1234
- gap: 12,
1235
- },
1236
- actionButton: {
1237
- flex: 1,
1238
- paddingVertical: 12,
1239
- paddingHorizontal: 16,
1240
- borderRadius: 8,
1241
- alignItems: 'center',
1242
- },
1243
- secondaryButton: {
1244
- backgroundColor: 'transparent',
1245
- borderWidth: 1,
1246
- },
1247
- actionButtonText: {
1248
- color: '#FFFFFF',
1249
- fontSize: 14,
1250
- fontWeight: '600',
1251
- },
1252
- billingToggle: {
1253
- flexDirection: 'row',
1254
- backgroundColor: 'rgba(0, 0, 0, 0.05)',
1255
- borderRadius: 8,
1256
- padding: 4,
1257
- marginBottom: 12,
1258
- },
1259
- billingOption: {
1260
- flex: 1,
1261
- paddingVertical: 12,
1262
- borderRadius: 6,
1263
- alignItems: 'center',
1264
- },
1265
- billingOptionText: {
1266
- fontSize: 16,
1267
- fontWeight: '600',
1268
- },
1269
- savingsText: {
1270
- fontSize: 14,
1271
- textAlign: 'center',
1272
- fontWeight: '600',
1273
- },
1274
- planCard: {
1275
- borderRadius: 16,
1276
- padding: 20,
1277
- marginBottom: 16,
1278
- borderWidth: 1,
1279
- position: 'relative',
1280
- },
1281
- popularPlan: {
1282
- borderWidth: 2,
1283
- },
1284
- popularBadge: {
1285
- position: 'absolute',
1286
- top: -1,
1287
- left: 20,
1288
- right: 20,
1289
- paddingVertical: 8,
1290
- borderTopLeftRadius: 16,
1291
- borderTopRightRadius: 16,
1292
- alignItems: 'center',
1293
- },
1294
- popularText: {
1295
- color: '#FFFFFF',
1296
- fontSize: 12,
1297
- fontWeight: 'bold',
1298
- },
1299
- planHeader: {
1300
- marginBottom: 16,
1301
- marginTop: 16,
1302
- },
1303
- planDescription: {
1304
- fontSize: 14,
1305
- lineHeight: 20,
1306
- },
1307
- planAppScope: {
1308
- fontSize: 12,
1309
- fontStyle: 'italic',
1310
- marginTop: 4,
1311
- },
1312
- planPricing: {
1313
- flexDirection: 'row',
1314
- alignItems: 'baseline',
1315
- marginBottom: 20,
1316
- },
1317
- planInterval: {
1318
- fontSize: 14,
1319
- marginLeft: 4,
1320
- },
1321
- planFeatures: {
1322
- marginBottom: 24,
1323
- },
1324
- featureItem: {
1325
- flexDirection: 'row',
1326
- alignItems: 'center',
1327
- marginBottom: 8,
1328
- },
1329
- featureText: {
1330
- fontSize: 14,
1331
- marginLeft: 8,
1332
- flex: 1,
1333
- },
1334
- selectPlanButton: {
1335
- paddingVertical: 16,
1336
- borderRadius: 12,
1337
- alignItems: 'center',
1338
- },
1339
- selectPlanText: {
1340
- fontSize: 16,
1341
- fontWeight: '600',
1342
- },
1343
- currentPlanButton: {
1344
- paddingVertical: 16,
1345
- borderRadius: 12,
1346
- alignItems: 'center',
1347
- },
1348
- currentPlanText: {
1349
- color: '#FFFFFF',
1350
- fontSize: 16,
1351
- fontWeight: '600',
1352
- },
1353
- benefitsCard: {
1354
- borderRadius: 16,
1355
- padding: 20,
1356
- borderWidth: 1,
1357
- },
1358
- benefitItem: {
1359
- flexDirection: 'row',
1360
- alignItems: 'flex-start',
1361
- marginBottom: 20,
1362
- },
1363
- benefitContent: {
1364
- marginLeft: 16,
1365
- flex: 1,
1366
- },
1367
- benefitTitle: {
1368
- fontSize: 16,
1369
- fontWeight: '600',
1370
- marginBottom: 4,
1371
- },
1372
- benefitDescription: {
1373
- fontSize: 14,
1374
- lineHeight: 20,
1375
- },
1376
- bottomSpacing: {
1377
- height: 40,
1378
- },
1379
- tabContainer: {
1380
- flexDirection: 'row',
1381
- borderBottomWidth: 1,
1382
- marginBottom: 20,
1383
- },
1384
- tab: {
1385
- flex: 1,
1386
- paddingVertical: 12,
1387
- paddingHorizontal: 16,
1388
- alignItems: 'center',
1389
- },
1390
- tabText: {
1391
- fontSize: 16,
1392
- fontWeight: '600',
1393
- },
1394
- featureCard: {
1395
- borderRadius: 12,
1396
- borderWidth: 1,
1397
- padding: 16,
1398
- marginBottom: 12,
1399
- },
1400
- featureHeader: {
1401
- flexDirection: 'row',
1402
- alignItems: 'flex-start',
1403
- marginBottom: 12,
1404
- },
1405
- featureIconContainer: {
1406
- width: 40,
1407
- height: 40,
1408
- borderRadius: 20,
1409
- backgroundColor: 'rgba(0, 122, 255, 0.1)',
1410
- justifyContent: 'center',
1411
- alignItems: 'center',
1412
- marginRight: 12,
1413
- },
1414
- featureInfo: {
1415
- flex: 1,
1416
- },
1417
- featureName: {
1418
- fontSize: 16,
1419
- fontWeight: '600',
1420
- marginBottom: 4,
1421
- },
1422
- featureDescription: {
1423
- fontSize: 14,
1424
- lineHeight: 20,
1425
- },
1426
- featurePricing: {
1427
- alignItems: 'center',
1428
- marginBottom: 16,
1429
- },
1430
- featurePrice: {
1431
- fontSize: 20,
1432
- fontWeight: 'bold',
1433
- },
1434
- featureInterval: {
1435
- fontSize: 14,
1436
- marginTop: 2,
1437
- },
1438
- featureActions: {
1439
- flexDirection: 'row',
1440
- gap: 8,
1441
- },
1442
- subscribedButton: {
1443
- flex: 1,
1444
- flexDirection: 'row',
1445
- justifyContent: 'center',
1446
- alignItems: 'center',
1447
- paddingVertical: 12,
1448
- borderRadius: 8,
1449
- gap: 6,
1450
- },
1451
- subscribedText: {
1452
- color: '#FFFFFF',
1453
- fontSize: 16,
1454
- fontWeight: '600',
1455
- },
1456
- unsubscribeButton: {
1457
- flex: 1,
1458
- justifyContent: 'center',
1459
- alignItems: 'center',
1460
- paddingVertical: 12,
1461
- borderRadius: 8,
1462
- borderWidth: 1,
1463
- },
1464
- unsubscribeText: {
1465
- fontSize: 16,
1466
- fontWeight: '600',
1467
- },
1468
- subscribeFeatureButton: {
1469
- justifyContent: 'center',
1470
- alignItems: 'center',
1471
- paddingVertical: 12,
1472
- borderRadius: 8,
1473
- },
1474
- subscribeFeatureText: {
1475
- color: '#FFFFFF',
1476
- fontSize: 16,
1477
- fontWeight: '600',
1478
- },
1479
- categorySection: {
1480
- marginBottom: 24,
1481
- },
1482
- categoryTitle: {
1483
- fontSize: 18,
1484
- fontWeight: '600',
1485
- marginBottom: 12,
1486
- },
1487
- featureNameRow: {
1488
- flexDirection: 'row',
1489
- alignItems: 'center',
1490
- justifyContent: 'space-between',
1491
- marginBottom: 4,
1492
- },
1493
- includedBadge: {
1494
- paddingHorizontal: 8,
1495
- paddingVertical: 2,
1496
- borderRadius: 12,
1497
- marginLeft: 8,
1498
- },
1499
- includedBadgeText: {
1500
- color: '#FFFFFF',
1501
- fontSize: 10,
1502
- fontWeight: '600',
1503
- textTransform: 'uppercase',
1504
- },
1505
- appScopeText: {
1506
- fontSize: 12,
1507
- marginTop: 4,
1508
- fontStyle: 'italic',
1509
- },
1510
- includedInPlanButton: {
1511
- flexDirection: 'row',
1512
- justifyContent: 'center',
1513
- alignItems: 'center',
1514
- paddingVertical: 12,
1515
- borderRadius: 8,
1516
- gap: 6,
1517
- },
1518
- includedInPlanText: {
1519
- color: '#FFFFFF',
1520
- fontSize: 14,
1521
- fontWeight: '600',
1522
- },
1523
- unavailableButton: {
1524
- justifyContent: 'center',
1525
- alignItems: 'center',
1526
- paddingVertical: 12,
1527
- borderRadius: 8,
1528
- },
1529
- unavailableText: {
1530
- fontSize: 14,
1531
- fontWeight: '500',
1532
- textAlign: 'center',
1533
- },
1534
- appSpecificBadge: {
1535
- position: 'absolute',
1536
- top: 16,
1537
- right: 16,
1538
- paddingHorizontal: 8,
1539
- paddingVertical: 4,
1540
- borderRadius: 12,
1541
- zIndex: 1,
1542
- },
1543
- appSpecificText: {
1544
- color: '#FFFFFF',
1545
- fontSize: 12,
1546
- fontWeight: '600',
1547
- },
1548
- planRestrictionText: {
1549
- fontSize: 12,
1550
- fontWeight: '500',
1551
- marginTop: 4,
1552
- fontStyle: 'italic',
1553
- },
1554
- unavailablePlanButton: {
1555
- paddingVertical: 16,
1556
- borderRadius: 12,
1557
- alignItems: 'center',
1558
- },
1559
- unavailablePlanText: {
1560
- fontSize: 16,
1561
- fontWeight: '600',
1562
- },
1563
- appSwitcher: {
1564
- padding: 16,
1565
- borderBottomWidth: 1,
1566
- margin: 16,
1567
- borderRadius: 12,
1568
- borderWidth: 1,
1569
- },
1570
- appSwitcherTitle: {
1571
- fontSize: 14,
1572
- fontWeight: '600',
1573
- marginBottom: 12,
1574
- },
1575
- appSwitcherButtons: {
1576
- flexDirection: 'row',
1577
- gap: 8,
1578
- },
1579
- appSwitcherButton: {
1580
- paddingHorizontal: 12,
1581
- paddingVertical: 6,
1582
- borderRadius: 8,
1583
- borderWidth: 1,
1584
- },
1585
- appSwitcherButtonText: {
1586
- fontSize: 12,
1587
- fontWeight: '500',
1588
- },
1589
- });
1590
-
1591
1138
  export default PremiumSubscriptionScreen;