@oxyhq/services 11.0.0 → 11.1.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.
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/AccountMenu.js +9 -5
- package/lib/commonjs/ui/components/AccountMenu.js.map +1 -1
- package/lib/commonjs/ui/components/AnotherDeviceQR.js +51 -56
- package/lib/commonjs/ui/components/AnotherDeviceQR.js.map +1 -1
- package/lib/commonjs/ui/components/BottomSheetRouter.js +1 -0
- package/lib/commonjs/ui/components/BottomSheetRouter.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +18 -5
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/OxyLogo.js +1 -1
- package/lib/commonjs/ui/components/OxyLogo.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +23 -7
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/SignInModal.js +20 -1
- package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/FileViewer.js +19 -9
- package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/UploadPreview.js +4 -2
- package/lib/commonjs/ui/components/fileManagement/UploadPreview.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +153 -19
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +6 -17
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/hooks/mutations/mutationFactory.js +5 -5
- package/lib/commonjs/ui/hooks/mutations/mutationFactory.js.map +1 -1
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +38 -38
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js +2 -2
- package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/queryKeys.js +3 -3
- package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +1 -1
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js +16 -12
- package/lib/commonjs/ui/hooks/queries/usePaymentQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +10 -6
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queryClient.js +6 -5
- package/lib/commonjs/ui/hooks/queryClient.js.map +1 -1
- package/lib/commonjs/ui/hooks/useOxyAuthSession.js +40 -2
- package/lib/commonjs/ui/hooks/useOxyAuthSession.js.map +1 -1
- package/lib/commonjs/ui/hooks/useProfileEditing.js +21 -0
- package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +3 -3
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountVerificationScreen.js +100 -108
- package/lib/commonjs/ui/screens/AccountVerificationScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +227 -273
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AvatarCropScreen.js +10 -4
- package/lib/commonjs/ui/screens/AvatarCropScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ConnectedAppsScreen.js +20 -37
- package/lib/commonjs/ui/screens/ConnectedAppsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js +89 -201
- package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +80 -208
- package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FAQScreen.js +56 -208
- package/lib/commonjs/ui/screens/FAQScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +303 -352
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +20 -20
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/HelpSupportScreen.js +77 -89
- package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/HistoryViewScreen.js +43 -58
- package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +67 -90
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js +77 -177
- package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LegalDocumentsScreen.js +113 -107
- package/lib/commonjs/ui/screens/LegalDocumentsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ManageAccountScreen.js +55 -114
- package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/NotificationsScreen.js +67 -85
- package/lib/commonjs/ui/screens/NotificationsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +71 -135
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +15 -9
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PreferencesScreen.js +65 -83
- package/lib/commonjs/ui/screens/PreferencesScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +378 -1023
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +294 -242
- package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ProfileScreen.js +194 -333
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SavesCollectionsScreen.js +57 -97
- package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SearchSettingsScreen.js +41 -41
- package/lib/commonjs/ui/screens/SearchSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/UserLinksScreen.js +17 -24
- package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/UserListScreen.js +83 -214
- package/lib/commonjs/ui/screens/UserListScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +115 -77
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js +70 -57
- package/lib/commonjs/ui/screens/trust/TrustAboutScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +136 -332
- package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustFAQScreen.js +47 -137
- package/lib/commonjs/ui/screens/trust/TrustFAQScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +182 -115
- package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +138 -214
- package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js +54 -92
- package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -1
- package/lib/commonjs/ui/utils/activeAuthuser.js +15 -9
- package/lib/commonjs/ui/utils/activeAuthuser.js.map +1 -1
- package/lib/commonjs/ui/utils/avatarUtils.js +1 -1
- package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/AccountMenu.js +10 -6
- package/lib/module/ui/components/AccountMenu.js.map +1 -1
- package/lib/module/ui/components/AnotherDeviceQR.js +50 -56
- package/lib/module/ui/components/AnotherDeviceQR.js.map +1 -1
- package/lib/module/ui/components/BottomSheetRouter.js +2 -1
- package/lib/module/ui/components/BottomSheetRouter.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +18 -5
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/OxyLogo.js +1 -1
- package/lib/module/ui/components/OxyLogo.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +23 -7
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/SignInModal.js +20 -1
- package/lib/module/ui/components/SignInModal.js.map +1 -1
- package/lib/module/ui/components/fileManagement/FileViewer.js +19 -9
- package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
- package/lib/module/ui/components/fileManagement/UploadPreview.js +4 -2
- package/lib/module/ui/components/fileManagement/UploadPreview.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +154 -20
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +6 -17
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/hooks/mutations/mutationFactory.js +5 -5
- package/lib/module/ui/hooks/mutations/mutationFactory.js.map +1 -1
- package/lib/module/ui/hooks/mutations/useAccountMutations.js +38 -38
- package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/module/ui/hooks/mutations/useServicesMutations.js +2 -2
- package/lib/module/ui/hooks/mutations/useServicesMutations.js.map +1 -1
- package/lib/module/ui/hooks/queries/queryKeys.js +3 -3
- package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/usePaymentQueries.js +16 -12
- package/lib/module/ui/hooks/queries/usePaymentQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js +9 -6
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/module/ui/hooks/queryClient.js +6 -5
- package/lib/module/ui/hooks/queryClient.js.map +1 -1
- package/lib/module/ui/hooks/useOxyAuthSession.js +40 -2
- package/lib/module/ui/hooks/useOxyAuthSession.js.map +1 -1
- package/lib/module/ui/hooks/useProfileEditing.js +21 -0
- package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js +4 -3
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/screens/AccountVerificationScreen.js +101 -109
- package/lib/module/ui/screens/AccountVerificationScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +228 -275
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/AvatarCropScreen.js +10 -4
- package/lib/module/ui/screens/AvatarCropScreen.js.map +1 -1
- package/lib/module/ui/screens/ConnectedAppsScreen.js +19 -39
- package/lib/module/ui/screens/ConnectedAppsScreen.js.map +1 -1
- package/lib/module/ui/screens/CreateManagedAccountScreen.js +90 -202
- package/lib/module/ui/screens/CreateManagedAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/EditProfileFieldScreen.js +77 -205
- package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
- package/lib/module/ui/screens/FAQScreen.js +55 -207
- package/lib/module/ui/screens/FAQScreen.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +301 -350
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +20 -20
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/HelpSupportScreen.js +78 -90
- package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
- package/lib/module/ui/screens/HistoryViewScreen.js +44 -59
- package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +68 -91
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/module/ui/screens/LearnMoreUsernamesScreen.js +75 -177
- package/lib/module/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
- package/lib/module/ui/screens/LegalDocumentsScreen.js +116 -108
- package/lib/module/ui/screens/LegalDocumentsScreen.js.map +1 -1
- package/lib/module/ui/screens/ManageAccountScreen.js +52 -112
- package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/NotificationsScreen.js +68 -86
- package/lib/module/ui/screens/NotificationsScreen.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +69 -134
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js +16 -10
- package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/module/ui/screens/PreferencesScreen.js +66 -84
- package/lib/module/ui/screens/PreferencesScreen.js.map +1 -1
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js +366 -1012
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/module/ui/screens/PrivacySettingsScreen.js +295 -243
- package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +192 -331
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/SavesCollectionsScreen.js +58 -98
- package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
- package/lib/module/ui/screens/SearchSettingsScreen.js +42 -42
- package/lib/module/ui/screens/SearchSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/UserLinksScreen.js +18 -25
- package/lib/module/ui/screens/UserLinksScreen.js.map +1 -1
- package/lib/module/ui/screens/UserListScreen.js +81 -212
- package/lib/module/ui/screens/UserListScreen.js.map +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js +114 -76
- package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustAboutScreen.js +69 -57
- package/lib/module/ui/screens/trust/TrustAboutScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustCenterScreen.js +135 -332
- package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustFAQScreen.js +48 -138
- package/lib/module/ui/screens/trust/TrustFAQScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +184 -117
- package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustRewardsScreen.js +132 -208
- package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustRulesScreen.js +58 -94
- package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -1
- package/lib/module/ui/utils/activeAuthuser.js +15 -9
- package/lib/module/ui/utils/activeAuthuser.js.map +1 -1
- package/lib/module/ui/utils/avatarUtils.js +1 -1
- package/lib/module/ui/utils/avatarUtils.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +2 -0
- package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts +12 -2
- package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/BottomSheetRouter.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts +3 -2
- package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/TouchableRipple/TouchableRipple.native.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/TouchableRipple/TouchableRipple.native.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +34 -0
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +6 -0
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts +3 -3
- package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queryClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts +22 -0
- package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useProfileEditing.d.ts +3 -0
- package/lib/typescript/commonjs/ui/hooks/useProfileEditing.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts +2 -1
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AppInfoScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/FAQScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/FeedbackScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/HelpSupportScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/HistoryViewScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/NotificationsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/PreferencesScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/UserLinksScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/UserListScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/AccountMenu.d.ts +2 -0
- package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts +12 -2
- package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/BottomSheetRouter.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyProvider.d.ts +3 -2
- package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.native.d.ts +1 -1
- package/lib/typescript/module/ui/components/TouchableRipple/TouchableRipple.native.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts +34 -0
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +6 -0
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts +3 -3
- package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queryClient.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts +22 -0
- package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useProfileEditing.d.ts +3 -0
- package/lib/typescript/module/ui/hooks/useProfileEditing.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +2 -1
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AppInfoScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/FAQScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/HelpSupportScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/LegalDocumentsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/NotificationsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/SearchSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/UserLinksScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/UserListScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustAboutScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustCenterScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustFAQScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustRewardsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +1 -1
- package/lib/typescript/types/expo-haptics.d.ts +42 -0
- package/package.json +8 -3
- package/src/index.ts +2 -0
- package/src/types/expo-haptics.d.ts +42 -0
- package/src/ui/components/AccountMenu.tsx +11 -5
- package/src/ui/components/AnotherDeviceQR.tsx +53 -45
- package/src/ui/components/BottomSheetRouter.tsx +2 -1
- package/src/ui/components/FollowButton.tsx +24 -5
- package/src/ui/components/OxyLogo.tsx +1 -1
- package/src/ui/components/OxyProvider.tsx +22 -8
- package/src/ui/components/SignInModal.tsx +21 -2
- package/src/ui/components/TouchableRipple/TouchableRipple.native.tsx +1 -1
- package/src/ui/components/fileManagement/FileViewer.tsx +9 -9
- package/src/ui/components/fileManagement/UploadPreview.tsx +2 -2
- package/src/ui/context/OxyContext.tsx +178 -21
- package/src/ui/context/hooks/useAuthOperations.ts +6 -17
- package/src/ui/hooks/mutations/mutationFactory.ts +5 -5
- package/src/ui/hooks/mutations/useAccountMutations.ts +38 -38
- package/src/ui/hooks/mutations/useServicesMutations.ts +2 -2
- package/src/ui/hooks/queries/queryKeys.ts +6 -3
- package/src/ui/hooks/queries/useAccountQueries.ts +1 -1
- package/src/ui/hooks/queries/usePaymentQueries.ts +12 -12
- package/src/ui/hooks/queries/useServicesQueries.ts +9 -6
- package/src/ui/hooks/queryClient.ts +5 -5
- package/src/ui/hooks/useOxyAuthSession.ts +76 -2
- package/src/ui/hooks/useProfileEditing.ts +24 -0
- package/src/ui/hooks/useSessionManagement.ts +9 -6
- package/src/ui/screens/AccountVerificationScreen.tsx +101 -113
- package/src/ui/screens/AppInfoScreen.tsx +200 -238
- package/src/ui/screens/AvatarCropScreen.tsx +17 -4
- package/src/ui/screens/ConnectedAppsScreen.tsx +16 -34
- package/src/ui/screens/CreateManagedAccountScreen.tsx +94 -170
- package/src/ui/screens/EditProfileFieldScreen.tsx +77 -190
- package/src/ui/screens/FAQScreen.tsx +77 -208
- package/src/ui/screens/FeedbackScreen.tsx +330 -239
- package/src/ui/screens/FileManagementScreen.tsx +20 -20
- package/src/ui/screens/HelpSupportScreen.tsx +67 -82
- package/src/ui/screens/HistoryViewScreen.tsx +32 -38
- package/src/ui/screens/LanguageSelectorScreen.tsx +79 -93
- package/src/ui/screens/LearnMoreUsernamesScreen.tsx +81 -164
- package/src/ui/screens/LegalDocumentsScreen.tsx +184 -123
- package/src/ui/screens/ManageAccountScreen.tsx +48 -114
- package/src/ui/screens/NotificationsScreen.tsx +107 -106
- package/src/ui/screens/OxyAuthScreen.tsx +76 -109
- package/src/ui/screens/PaymentGatewayScreen.tsx +16 -7
- package/src/ui/screens/PreferencesScreen.tsx +96 -116
- package/src/ui/screens/PremiumSubscriptionScreen.tsx +419 -872
- package/src/ui/screens/PrivacySettingsScreen.tsx +203 -185
- package/src/ui/screens/ProfileScreen.tsx +162 -246
- package/src/ui/screens/SavesCollectionsScreen.tsx +78 -125
- package/src/ui/screens/SearchSettingsScreen.tsx +52 -41
- package/src/ui/screens/UserLinksScreen.tsx +18 -25
- package/src/ui/screens/UserListScreen.tsx +95 -188
- package/src/ui/screens/WelcomeNewUserScreen.tsx +109 -36
- package/src/ui/screens/trust/TrustAboutScreen.tsx +52 -41
- package/src/ui/screens/trust/TrustCenterScreen.tsx +184 -222
- package/src/ui/screens/trust/TrustFAQScreen.tsx +64 -124
- package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +190 -67
- package/src/ui/screens/trust/TrustRewardsScreen.tsx +147 -182
- package/src/ui/screens/trust/TrustRulesScreen.tsx +77 -50
- package/src/ui/utils/activeAuthuser.ts +15 -9
- package/src/ui/utils/avatarUtils.ts +1 -1
- package/lib/commonjs/ui/components/feedback/FormInput.js +0 -72
- package/lib/commonjs/ui/components/feedback/FormInput.js.map +0 -1
- package/lib/commonjs/ui/components/feedback/feedbackStyles.js +0 -261
- package/lib/commonjs/ui/components/feedback/feedbackStyles.js.map +0 -1
- package/lib/module/ui/components/feedback/FormInput.js +0 -67
- package/lib/module/ui/components/feedback/FormInput.js.map +0 -1
- package/lib/module/ui/components/feedback/feedbackStyles.js +0 -256
- package/lib/module/ui/components/feedback/feedbackStyles.js.map +0 -1
- package/lib/typescript/commonjs/ui/components/feedback/FormInput.d.ts +0 -20
- package/lib/typescript/commonjs/ui/components/feedback/FormInput.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/feedback/feedbackStyles.d.ts +0 -279
- package/lib/typescript/commonjs/ui/components/feedback/feedbackStyles.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/feedback/FormInput.d.ts +0 -20
- package/lib/typescript/module/ui/components/feedback/FormInput.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/feedback/feedbackStyles.d.ts +0 -279
- package/lib/typescript/module/ui/components/feedback/feedbackStyles.d.ts.map +0 -1
- package/src/ui/components/feedback/FormInput.tsx +0 -84
- 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
|
|
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
|
|
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<
|
|
78
|
-
const [activeTab, setActiveTab] = useState<
|
|
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() +
|
|
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
|
|
379
|
-
if (!
|
|
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,
|
|
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() +
|
|
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,
|
|
443
|
-
const yearlyPrice = interval === 'year' ? price : price *
|
|
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
|
|
461
|
-
if (!
|
|
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 (
|
|
467
|
-
const hasExactMatch =
|
|
468
|
-
|
|
469
|
-
if (!hasExactMatch &&
|
|
470
|
-
const requiredApp =
|
|
471
|
-
toast.error(`${
|
|
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,
|
|
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
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
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
|
|
569
|
-
subscription.status === 'active' ?
|
|
570
|
-
subscription.status === 'trialing' ?
|
|
571
|
-
|
|
559
|
+
const statusChipColor =
|
|
560
|
+
subscription.status === 'active' ? 'success' :
|
|
561
|
+
subscription.status === 'trialing' ? 'warning' :
|
|
562
|
+
'error';
|
|
572
563
|
|
|
573
564
|
return (
|
|
574
|
-
<View
|
|
575
|
-
<
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
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
|
|
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
|
|
598
|
-
<Ionicons name="warning" size={16} color={
|
|
599
|
-
<Text
|
|
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
|
|
596
|
+
<View className="flex-row gap-space-12">
|
|
606
597
|
{subscription.cancelAtPeriodEnd ? (
|
|
607
|
-
<
|
|
608
|
-
|
|
598
|
+
<Button
|
|
599
|
+
variant="primary"
|
|
609
600
|
onPress={handleReactivateSubscription}
|
|
601
|
+
className="flex-1"
|
|
602
|
+
accessibilityLabel={t('premium.actions.reactivate') || 'Reactivate'}
|
|
610
603
|
>
|
|
611
|
-
|
|
612
|
-
</
|
|
604
|
+
{t('premium.actions.reactivate') || 'Reactivate'}
|
|
605
|
+
</Button>
|
|
613
606
|
) : (
|
|
614
|
-
<
|
|
615
|
-
|
|
607
|
+
<Button
|
|
608
|
+
variant="destructive"
|
|
616
609
|
onPress={confirmCancelSubscription}
|
|
610
|
+
className="flex-1"
|
|
611
|
+
accessibilityLabel={t('premium.actions.cancelSubBtn') || 'Cancel Subscription'}
|
|
617
612
|
>
|
|
618
|
-
|
|
619
|
-
</
|
|
613
|
+
{t('premium.actions.cancelSubBtn') || 'Cancel Subscription'}
|
|
614
|
+
</Button>
|
|
620
615
|
)}
|
|
621
616
|
|
|
622
|
-
<
|
|
623
|
-
|
|
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
|
-
|
|
627
|
-
</
|
|
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
|
|
636
|
-
<
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
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
|
-
</
|
|
650
|
-
</
|
|
651
|
-
|
|
652
|
-
|
|
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
|
-
</
|
|
665
|
-
</
|
|
666
|
-
</
|
|
647
|
+
</SegmentedControlItemText>
|
|
648
|
+
</SegmentedControlItem>
|
|
649
|
+
</SegmentedControl>
|
|
667
650
|
|
|
668
651
|
{billingInterval === 'year' && (
|
|
669
|
-
<Text
|
|
670
|
-
{t('premium.billing.saveYearly') || '
|
|
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.
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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
|
-
|
|
718
|
-
|
|
719
|
-
<
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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
|
|
734
|
-
<
|
|
735
|
-
<Text
|
|
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
|
|
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={
|
|
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
|
|
749
|
-
<
|
|
750
|
-
|
|
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
|
-
<
|
|
741
|
+
<BenefitList className="mb-space-24">
|
|
758
742
|
{plan.features.map((feature, index) => (
|
|
759
|
-
<
|
|
760
|
-
|
|
761
|
-
<
|
|
762
|
-
|
|
743
|
+
<BenefitRow
|
|
744
|
+
key={index}
|
|
745
|
+
icon={<Ionicons name="checkmark" size={18} color={colors.success} />}
|
|
746
|
+
label={feature}
|
|
747
|
+
/>
|
|
763
748
|
))}
|
|
764
|
-
</
|
|
749
|
+
</BenefitList>
|
|
765
750
|
|
|
766
751
|
{isCurrentPlan ? (
|
|
767
|
-
<
|
|
768
|
-
|
|
769
|
-
|
|
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
|
-
<
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
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
|
-
<
|
|
778
|
-
|
|
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
|
-
{
|
|
786
|
-
|
|
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
|
|
803
|
-
<
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
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
|
-
</
|
|
817
|
-
</
|
|
818
|
-
|
|
819
|
-
|
|
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
|
-
</
|
|
832
|
-
</
|
|
833
|
-
</
|
|
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.
|
|
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
|
|
846
|
-
case 'customization': return
|
|
847
|
-
case 'content': return
|
|
848
|
-
case 'networking': return
|
|
849
|
-
case 'productivity': return
|
|
850
|
-
default: return
|
|
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
|
-
|
|
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
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
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
|
|
883
|
-
<View
|
|
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)
|
|
861
|
+
name={getCategoryIcon(feature.category)}
|
|
886
862
|
size={24}
|
|
887
863
|
color={getCategoryColor(feature.category)}
|
|
888
864
|
/>
|
|
889
865
|
</View>
|
|
890
|
-
<View
|
|
891
|
-
<View
|
|
892
|
-
<
|
|
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
|
-
<
|
|
895
|
-
|
|
896
|
-
</
|
|
870
|
+
<Chip variant="solid" color="primary" size="small">
|
|
871
|
+
{t('premium.feature.included') || 'Included'}
|
|
872
|
+
</Chip>
|
|
897
873
|
)}
|
|
898
874
|
</View>
|
|
899
|
-
<Text
|
|
875
|
+
<Text className="text-text-secondary text-sm">
|
|
900
876
|
{feature.description}
|
|
901
877
|
</Text>
|
|
902
|
-
<Text
|
|
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
|
|
910
|
-
<
|
|
911
|
-
|
|
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
|
-
<
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
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
|
|
926
|
-
<
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
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
|
-
|
|
935
|
-
</
|
|
920
|
+
{t('premium.actions.unsubscribe') || 'Unsubscribe'}
|
|
921
|
+
</Button>
|
|
936
922
|
</View>
|
|
937
923
|
) : canPurchase ? (
|
|
938
|
-
<
|
|
939
|
-
|
|
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
|
-
{
|
|
944
|
-
|
|
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
|
-
<
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
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
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
<
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
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
|
-
//
|
|
988
|
-
const [showAppSwitcher
|
|
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
|
|
997
|
-
<Text
|
|
998
|
-
|
|
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
|
|
987
|
+
<View className="flex-row gap-space-8">
|
|
1002
988
|
{testApps.map(app => (
|
|
1003
|
-
<
|
|
989
|
+
<Chip
|
|
1004
990
|
key={app}
|
|
1005
|
-
|
|
1006
|
-
|
|
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
|
-
|
|
1017
|
-
|
|
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
|
|
1033
|
-
<
|
|
1034
|
-
|
|
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
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
{
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1067
|
-
</View>
|
|
1068
|
-
) : (
|
|
1069
|
-
renderIndividualFeatures()
|
|
1070
|
-
)}
|
|
1059
|
+
{!subscription && activeTab === TAB_PLANS && renderBillingToggle()}
|
|
1071
1060
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
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;
|