@oxyhq/services 6.9.4 → 6.9.6
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/ui/client.js +0 -7
- package/lib/commonjs/ui/client.js.map +1 -1
- package/lib/commonjs/ui/components/BottomSheet.js +5 -3
- package/lib/commonjs/ui/components/BottomSheet.js.map +1 -1
- package/lib/commonjs/ui/components/FontLoader.js +1 -1
- package/lib/commonjs/ui/components/FontLoader.js.map +1 -1
- package/lib/commonjs/ui/components/Header.js.map +1 -1
- package/lib/commonjs/ui/components/HelperText.js +1 -1
- package/lib/commonjs/ui/components/HelperText.js.map +1 -1
- package/lib/commonjs/ui/components/Icon.js +6 -2
- package/lib/commonjs/ui/components/Icon.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +9 -1
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/QuickActions.js.map +1 -1
- package/lib/commonjs/ui/components/SignInModal.js +5 -4
- package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
- package/lib/commonjs/ui/components/TouchableRipple/Pressable.js.map +1 -1
- package/lib/commonjs/ui/components/feedback/FormInput.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/AnimatedButton.js.map +1 -1
- package/lib/commonjs/ui/components/icon/OxyIcon.js.map +1 -1
- package/lib/commonjs/ui/components/modals/DeleteAccountModal.js +1 -1
- package/lib/commonjs/ui/components/modals/DeleteAccountModal.js.map +1 -1
- package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js +26 -20
- package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js.map +1 -1
- package/lib/commonjs/ui/components/payment/PaymentMethodStep.js +9 -5
- package/lib/commonjs/ui/components/payment/PaymentMethodStep.js.map +1 -1
- package/lib/commonjs/ui/components/payment/PaymentReviewStep.js +19 -13
- package/lib/commonjs/ui/components/payment/PaymentReviewStep.js.map +1 -1
- package/lib/commonjs/ui/components/payment/PaymentSuccessStep.js +9 -5
- package/lib/commonjs/ui/components/payment/PaymentSuccessStep.js.map +1 -1
- package/lib/commonjs/ui/components/payment/PaymentSummaryStep.js +14 -10
- package/lib/commonjs/ui/components/payment/PaymentSummaryStep.js.map +1 -1
- package/lib/commonjs/ui/components/types.js +4 -0
- package/lib/commonjs/ui/hooks/useAssets.js +4 -4
- package/lib/commonjs/ui/hooks/useAssets.js.map +1 -1
- package/lib/commonjs/ui/hooks/useAsyncAction.js +2 -2
- package/lib/commonjs/ui/hooks/useAsyncAction.js.map +1 -1
- package/lib/commonjs/ui/hooks/useFollow.js.map +1 -1
- package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSettingToggle.js +2 -2
- package/lib/commonjs/ui/hooks/useSettingToggle.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +3 -3
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountVerificationScreen.js +1 -1
- package/lib/commonjs/ui/screens/AccountVerificationScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +66 -60
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +2 -2
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +139 -79
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +2 -2
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js +22 -17
- package/lib/commonjs/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +2 -2
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +6 -2
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js +39 -29
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/UserLinksScreen.js +11 -3
- package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/commonjs/ui/stores/followStore.js +2 -2
- package/lib/commonjs/ui/stores/followStore.js.map +1 -1
- package/lib/commonjs/ui/utils/errorHandlers.js +2 -2
- package/lib/commonjs/ui/utils/errorHandlers.js.map +1 -1
- package/lib/commonjs/ui/utils/fileManagement.js +8 -3
- package/lib/commonjs/ui/utils/fileManagement.js.map +1 -1
- package/lib/commonjs/ui/utils/sessionHelpers.js +3 -2
- package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/commonjs/ui/utils/storageHelpers.js +1 -1
- package/lib/commonjs/ui/utils/storageHelpers.js.map +1 -1
- package/lib/commonjs/utils/hookUtils.js +4 -0
- package/lib/commonjs/utils/hookUtils.js.map +1 -1
- package/lib/module/ui/client.js +0 -1
- package/lib/module/ui/client.js.map +1 -1
- package/lib/module/ui/components/BottomSheet.js +5 -3
- package/lib/module/ui/components/BottomSheet.js.map +1 -1
- package/lib/module/ui/components/FontLoader.js +1 -1
- package/lib/module/ui/components/FontLoader.js.map +1 -1
- package/lib/module/ui/components/Header.js.map +1 -1
- package/lib/module/ui/components/HelperText.js +1 -1
- package/lib/module/ui/components/HelperText.js.map +1 -1
- package/lib/module/ui/components/Icon.js +6 -2
- package/lib/module/ui/components/Icon.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +9 -1
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/QuickActions.js.map +1 -1
- package/lib/module/ui/components/SignInModal.js +5 -4
- package/lib/module/ui/components/SignInModal.js.map +1 -1
- package/lib/module/ui/components/TouchableRipple/Pressable.js.map +1 -1
- package/lib/module/ui/components/feedback/FormInput.js.map +1 -1
- package/lib/module/ui/components/fileManagement/AnimatedButton.js.map +1 -1
- package/lib/module/ui/components/icon/OxyIcon.js.map +1 -1
- package/lib/module/ui/components/modals/DeleteAccountModal.js +1 -1
- package/lib/module/ui/components/modals/DeleteAccountModal.js.map +1 -1
- package/lib/module/ui/components/payment/PaymentDetailsStep.js +26 -20
- package/lib/module/ui/components/payment/PaymentDetailsStep.js.map +1 -1
- package/lib/module/ui/components/payment/PaymentMethodStep.js +9 -5
- package/lib/module/ui/components/payment/PaymentMethodStep.js.map +1 -1
- package/lib/module/ui/components/payment/PaymentReviewStep.js +19 -13
- package/lib/module/ui/components/payment/PaymentReviewStep.js.map +1 -1
- package/lib/module/ui/components/payment/PaymentSuccessStep.js +9 -5
- package/lib/module/ui/components/payment/PaymentSuccessStep.js.map +1 -1
- package/lib/module/ui/components/payment/PaymentSummaryStep.js +14 -10
- package/lib/module/ui/components/payment/PaymentSummaryStep.js.map +1 -1
- package/lib/module/ui/components/types.js +2 -0
- package/lib/module/ui/hooks/useAssets.js +4 -4
- package/lib/module/ui/hooks/useAssets.js.map +1 -1
- package/lib/module/ui/hooks/useAsyncAction.js +2 -2
- package/lib/module/ui/hooks/useAsyncAction.js.map +1 -1
- package/lib/module/ui/hooks/useFollow.js.map +1 -1
- package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/module/ui/hooks/useSettingToggle.js +2 -2
- package/lib/module/ui/hooks/useSettingToggle.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +3 -3
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountVerificationScreen.js +1 -1
- package/lib/module/ui/screens/AccountVerificationScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +66 -60
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +2 -2
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +139 -79
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +2 -2
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/module/ui/screens/LearnMoreUsernamesScreen.js +22 -17
- package/lib/module/ui/screens/LearnMoreUsernamesScreen.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +2 -2
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js +6 -2
- package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js +39 -29
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/UserLinksScreen.js +11 -3
- package/lib/module/ui/screens/UserLinksScreen.js.map +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +1 -1
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/module/ui/stores/followStore.js +2 -2
- package/lib/module/ui/stores/followStore.js.map +1 -1
- package/lib/module/ui/utils/errorHandlers.js +2 -2
- package/lib/module/ui/utils/errorHandlers.js.map +1 -1
- package/lib/module/ui/utils/fileManagement.js +8 -3
- package/lib/module/ui/utils/fileManagement.js.map +1 -1
- package/lib/module/ui/utils/sessionHelpers.js +3 -2
- package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/module/ui/utils/storageHelpers.js +1 -1
- package/lib/module/ui/utils/storageHelpers.js.map +1 -1
- package/lib/module/utils/hookUtils.js +4 -0
- package/lib/module/utils/hookUtils.js.map +1 -1
- package/lib/typescript/commonjs/ui/client.d.ts +0 -1
- package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/BottomSheet.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/Icon.d.ts.map +1 -1
- 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/TextField/Adornment/types.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/TextField/Adornment/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/TouchableRipple/Pressable.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/fileManagement/AnimatedButton.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/fileManagement/AnimatedButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/payment/PaymentDetailsStep.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/payment/PaymentMethodStep.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/payment/PaymentReviewStep.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/payment/PaymentSuccessStep.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/payment/PaymentSummaryStep.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/types.d.ts +18 -17
- package/lib/typescript/commonjs/ui/components/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AppInfoScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/UserLinksScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/types/navigation.d.ts +2 -0
- package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts +1 -1
- package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/sessionHelpers.d.ts +2 -1
- package/lib/typescript/commonjs/ui/utils/sessionHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/hookUtils.d.ts.map +1 -1
- package/lib/typescript/module/ui/client.d.ts +0 -1
- package/lib/typescript/module/ui/client.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/BottomSheet.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/Icon.d.ts.map +1 -1
- 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/TextField/Adornment/types.d.ts +1 -1
- package/lib/typescript/module/ui/components/TextField/Adornment/types.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/TouchableRipple/Pressable.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/fileManagement/AnimatedButton.d.ts +1 -1
- package/lib/typescript/module/ui/components/fileManagement/AnimatedButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/payment/PaymentDetailsStep.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/payment/PaymentMethodStep.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/payment/PaymentReviewStep.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/payment/PaymentSuccessStep.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/payment/PaymentSummaryStep.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/types.d.ts +18 -17
- package/lib/typescript/module/ui/components/types.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AppInfoScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/LearnMoreUsernamesScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/UserLinksScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/types/navigation.d.ts +2 -0
- package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/fileManagement.d.ts +1 -1
- package/lib/typescript/module/ui/utils/fileManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/sessionHelpers.d.ts +2 -1
- package/lib/typescript/module/ui/utils/sessionHelpers.d.ts.map +1 -1
- package/lib/typescript/module/utils/hookUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ui/client.ts +0 -1
- package/src/ui/components/BottomSheet.tsx +4 -3
- package/src/ui/components/FontLoader.tsx +1 -1
- package/src/ui/components/Header.tsx +2 -2
- package/src/ui/components/HelperText.tsx +1 -1
- package/src/ui/components/Icon.tsx +2 -0
- package/src/ui/components/OxyProvider.tsx +6 -0
- package/src/ui/components/QuickActions.tsx +1 -1
- package/src/ui/components/SignInModal.tsx +6 -5
- package/src/ui/components/TextField/Adornment/types.tsx +1 -1
- package/src/ui/components/TouchableRipple/Pressable.tsx +1 -0
- package/src/ui/components/feedback/FormInput.tsx +1 -1
- package/src/ui/components/fileManagement/AnimatedButton.tsx +2 -2
- package/src/ui/components/icon/OxyIcon.tsx +1 -1
- package/src/ui/components/modals/DeleteAccountModal.tsx +2 -2
- package/src/ui/components/payment/PaymentDetailsStep.tsx +24 -22
- package/src/ui/components/payment/PaymentMethodStep.tsx +7 -5
- package/src/ui/components/payment/PaymentReviewStep.tsx +15 -13
- package/src/ui/components/payment/PaymentSuccessStep.tsx +7 -5
- package/src/ui/components/payment/PaymentSummaryStep.tsx +12 -10
- package/src/ui/components/types.tsx +19 -17
- package/src/ui/hooks/useAssets.ts +8 -8
- package/src/ui/hooks/useAsyncAction.ts +4 -4
- package/src/ui/hooks/useFollow.ts +1 -1
- package/src/ui/hooks/useProfileEditing.ts +1 -1
- package/src/ui/hooks/useSettingToggle.ts +4 -4
- package/src/ui/screens/AccountOverviewScreen.tsx +6 -6
- package/src/ui/screens/AccountVerificationScreen.tsx +2 -2
- package/src/ui/screens/AppInfoScreen.tsx +63 -61
- package/src/ui/screens/FeedbackScreen.tsx +3 -3
- package/src/ui/screens/FileManagementScreen.tsx +130 -121
- package/src/ui/screens/LanguageSelectorScreen.tsx +3 -3
- package/src/ui/screens/LearnMoreUsernamesScreen.tsx +22 -19
- package/src/ui/screens/OxyAuthScreen.tsx +3 -3
- package/src/ui/screens/PaymentGatewayScreen.tsx +4 -2
- package/src/ui/screens/SessionManagementScreen.tsx +30 -28
- package/src/ui/screens/UserLinksScreen.tsx +5 -3
- package/src/ui/screens/WelcomeNewUserScreen.tsx +2 -2
- package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +1 -1
- package/src/ui/screens/karma/KarmaRulesScreen.tsx +1 -1
- package/src/ui/stores/followStore.ts +4 -4
- package/src/ui/types/navigation.ts +2 -0
- package/src/ui/utils/errorHandlers.ts +2 -2
- package/src/ui/utils/fileManagement.ts +13 -8
- package/src/ui/utils/sessionHelpers.ts +3 -2
- package/src/ui/utils/storageHelpers.ts +1 -1
- package/src/utils/hookUtils.ts +4 -2
- package/lib/commonjs/ui/components/AnimationExample.js +0 -213
- package/lib/commonjs/ui/components/AnimationExample.js.map +0 -1
- package/lib/commonjs/ui/components/ErrorBoundary.js +0 -145
- package/lib/commonjs/ui/components/ErrorBoundary.js.map +0 -1
- package/lib/commonjs/ui/components/WebOxyProvider.js +0 -106
- package/lib/commonjs/ui/components/WebOxyProvider.js.map +0 -1
- package/lib/module/ui/components/AnimationExample.js +0 -209
- package/lib/module/ui/components/AnimationExample.js.map +0 -1
- package/lib/module/ui/components/ErrorBoundary.js +0 -139
- package/lib/module/ui/components/ErrorBoundary.js.map +0 -1
- package/lib/module/ui/components/WebOxyProvider.js +0 -102
- package/lib/module/ui/components/WebOxyProvider.js.map +0 -1
- package/lib/typescript/commonjs/ui/components/AnimationExample.d.ts +0 -4
- package/lib/typescript/commonjs/ui/components/AnimationExample.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/ErrorBoundary.d.ts +0 -31
- package/lib/typescript/commonjs/ui/components/ErrorBoundary.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/WebOxyProvider.d.ts +0 -52
- package/lib/typescript/commonjs/ui/components/WebOxyProvider.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/AnimationExample.d.ts +0 -4
- package/lib/typescript/module/ui/components/AnimationExample.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/ErrorBoundary.d.ts +0 -31
- package/lib/typescript/module/ui/components/ErrorBoundary.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/WebOxyProvider.d.ts +0 -52
- package/lib/typescript/module/ui/components/WebOxyProvider.d.ts.map +0 -1
- package/src/ui/components/AnimationExample.tsx +0 -195
- package/src/ui/components/ErrorBoundary.tsx +0 -154
- package/src/ui/components/WebOxyProvider.tsx +0 -117
|
@@ -58,11 +58,11 @@ const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
|
|
|
58
58
|
if (isAuthenticated && user?.id) {
|
|
59
59
|
try {
|
|
60
60
|
await oxyServices.updateProfile({ language: languageId });
|
|
61
|
-
} catch (e:
|
|
61
|
+
} catch (e: unknown) {
|
|
62
62
|
// Server sync failed, but we'll save locally anyway
|
|
63
63
|
serverSyncFailed = true;
|
|
64
64
|
if (__DEV__) {
|
|
65
|
-
console.warn('Failed to sync language to server (will save locally only):', e
|
|
65
|
+
console.warn('Failed to sync language to server (will save locally only):', e instanceof Error ? e.message : e);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -89,7 +89,7 @@ const LanguageSelectorScreen: React.FC<LanguageSelectorScreenProps> = ({
|
|
|
89
89
|
if (__DEV__) {
|
|
90
90
|
console.error('Error saving language preference:', error);
|
|
91
91
|
}
|
|
92
|
-
toast.error('
|
|
92
|
+
toast.error(t('language.saveFailed'));
|
|
93
93
|
setIsLoading(false);
|
|
94
94
|
}
|
|
95
95
|
}, [currentLanguage, isLoading, isAuthenticated, user?.id, oxyServices, setLanguage, t, onClose, goBack]);
|
|
@@ -10,43 +10,44 @@ import {
|
|
|
10
10
|
import { Ionicons } from '@expo/vector-icons';
|
|
11
11
|
import type { BaseScreenProps } from '../types/navigation';
|
|
12
12
|
import { useThemeStyles } from '../hooks/useThemeStyles';
|
|
13
|
+
import { useI18n } from '../hooks/useI18n';
|
|
13
14
|
|
|
14
15
|
interface InfoSection {
|
|
15
16
|
id: string;
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
titleKey: string;
|
|
18
|
+
contentKey: string;
|
|
18
19
|
icon: string;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
const INFO_SECTIONS: InfoSection[] = [
|
|
22
23
|
{
|
|
23
24
|
id: 'what',
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
titleKey: 'learnMoreUsernames.sections.what.title',
|
|
26
|
+
contentKey: 'learnMoreUsernames.sections.what.content',
|
|
26
27
|
icon: 'at-outline',
|
|
27
28
|
},
|
|
28
29
|
{
|
|
29
30
|
id: 'rules',
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
titleKey: 'learnMoreUsernames.sections.rules.title',
|
|
32
|
+
contentKey: 'learnMoreUsernames.sections.rules.content',
|
|
32
33
|
icon: 'list-outline',
|
|
33
34
|
},
|
|
34
35
|
{
|
|
35
36
|
id: 'unique',
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
titleKey: 'learnMoreUsernames.sections.unique.title',
|
|
38
|
+
contentKey: 'learnMoreUsernames.sections.unique.content',
|
|
38
39
|
icon: 'finger-print-outline',
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
42
|
id: 'change',
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
titleKey: 'learnMoreUsernames.sections.change.title',
|
|
44
|
+
contentKey: 'learnMoreUsernames.sections.change.content',
|
|
44
45
|
icon: 'refresh-outline',
|
|
45
46
|
},
|
|
46
47
|
{
|
|
47
48
|
id: 'tips',
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
titleKey: 'learnMoreUsernames.sections.tips.title',
|
|
50
|
+
contentKey: 'learnMoreUsernames.sections.tips.content',
|
|
50
51
|
icon: 'bulb-outline',
|
|
51
52
|
},
|
|
52
53
|
];
|
|
@@ -55,6 +56,7 @@ const LearnMoreUsernamesScreen: React.FC<BaseScreenProps> = ({
|
|
|
55
56
|
theme,
|
|
56
57
|
}) => {
|
|
57
58
|
const themeStyles = useThemeStyles(theme || 'light');
|
|
59
|
+
const { t } = useI18n();
|
|
58
60
|
const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set(['what'])); // Start with first section expanded
|
|
59
61
|
|
|
60
62
|
const toggleExpanded = useCallback((id: string) => {
|
|
@@ -83,15 +85,16 @@ const LearnMoreUsernamesScreen: React.FC<BaseScreenProps> = ({
|
|
|
83
85
|
<Ionicons name="at" size={32} color={themeStyles.primaryColor} />
|
|
84
86
|
</View>
|
|
85
87
|
<Text style={[styles.introTitle, { color: themeStyles.textColor }]}>
|
|
86
|
-
|
|
88
|
+
{t('learnMoreUsernames.introTitle')}
|
|
87
89
|
</Text>
|
|
88
90
|
<Text style={[styles.introText, { color: themeStyles.mutedTextColor }]}>
|
|
89
|
-
|
|
91
|
+
{t('learnMoreUsernames.introText')}
|
|
90
92
|
</Text>
|
|
91
93
|
</View>
|
|
92
94
|
|
|
93
95
|
{INFO_SECTIONS.map((section, index) => {
|
|
94
96
|
const isExpanded = expandedIds.has(section.id);
|
|
97
|
+
const sectionTitle = t(section.titleKey);
|
|
95
98
|
return (
|
|
96
99
|
<View
|
|
97
100
|
key={section.id}
|
|
@@ -105,8 +108,8 @@ const LearnMoreUsernamesScreen: React.FC<BaseScreenProps> = ({
|
|
|
105
108
|
style={styles.sectionHeader}
|
|
106
109
|
onPress={() => toggleExpanded(section.id)}
|
|
107
110
|
accessibilityRole="button"
|
|
108
|
-
accessibilityLabel={
|
|
109
|
-
accessibilityHint={isExpanded ? '
|
|
111
|
+
accessibilityLabel={sectionTitle}
|
|
112
|
+
accessibilityHint={isExpanded ? t('learnMoreUsernames.collapseHint') : t('learnMoreUsernames.expandHint')}
|
|
110
113
|
accessibilityState={{ expanded: isExpanded }}
|
|
111
114
|
>
|
|
112
115
|
<View style={[styles.sectionIconContainer, { backgroundColor: `${themeStyles.primaryColor}15` }]}>
|
|
@@ -117,7 +120,7 @@ const LearnMoreUsernamesScreen: React.FC<BaseScreenProps> = ({
|
|
|
117
120
|
/>
|
|
118
121
|
</View>
|
|
119
122
|
<Text style={[styles.sectionTitle, { color: themeStyles.textColor }]}>
|
|
120
|
-
{
|
|
123
|
+
{sectionTitle}
|
|
121
124
|
</Text>
|
|
122
125
|
<Ionicons
|
|
123
126
|
name={isExpanded ? 'chevron-up' : 'chevron-down'}
|
|
@@ -128,7 +131,7 @@ const LearnMoreUsernamesScreen: React.FC<BaseScreenProps> = ({
|
|
|
128
131
|
{isExpanded && (
|
|
129
132
|
<View style={[styles.sectionContent, { borderTopColor: themeStyles.borderColor }]}>
|
|
130
133
|
<Text style={[styles.sectionText, { color: themeStyles.mutedTextColor }]}>
|
|
131
|
-
{section.
|
|
134
|
+
{t(section.contentKey)}
|
|
132
135
|
</Text>
|
|
133
136
|
</View>
|
|
134
137
|
)}
|
|
@@ -138,7 +141,7 @@ const LearnMoreUsernamesScreen: React.FC<BaseScreenProps> = ({
|
|
|
138
141
|
|
|
139
142
|
<View style={styles.footer}>
|
|
140
143
|
<Text style={[styles.footerText, { color: themeStyles.mutedTextColor }]}>
|
|
141
|
-
|
|
144
|
+
{t('learnMoreUsernames.footer')}
|
|
142
145
|
</Text>
|
|
143
146
|
</View>
|
|
144
147
|
</ScrollView>
|
|
@@ -200,7 +200,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
200
200
|
});
|
|
201
201
|
|
|
202
202
|
socket.on('connect_error', (err) => {
|
|
203
|
-
debug.log('Socket connection error, falling back to polling:', err.message);
|
|
203
|
+
debug.log('Socket connection error, falling back to polling:', (err instanceof Error ? err.message : null));
|
|
204
204
|
// Fall back to polling if socket fails
|
|
205
205
|
socket.disconnect();
|
|
206
206
|
startPolling(sessionToken);
|
|
@@ -281,8 +281,8 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
281
281
|
|
|
282
282
|
// Try socket first, will fall back to polling if needed
|
|
283
283
|
connectSocket(sessionToken);
|
|
284
|
-
} catch (err:
|
|
285
|
-
setError(err.message || 'Failed to create auth session');
|
|
284
|
+
} catch (err: unknown) {
|
|
285
|
+
setError((err instanceof Error ? err.message : null) || 'Failed to create auth session');
|
|
286
286
|
} finally {
|
|
287
287
|
setIsLoading(false);
|
|
288
288
|
}
|
|
@@ -13,6 +13,7 @@ import { useThemeColors } from '../styles';
|
|
|
13
13
|
import { normalizeTheme } from '../utils/themeUtils';
|
|
14
14
|
import GroupedPillButtons from '../components/internal/GroupedPillButtons';
|
|
15
15
|
import { useThemeStyles } from '../hooks/useThemeStyles';
|
|
16
|
+
import { useI18n } from '../hooks/useI18n';
|
|
16
17
|
import QRCode from 'react-native-qrcode-svg';
|
|
17
18
|
|
|
18
19
|
import {
|
|
@@ -80,6 +81,7 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
|
|
|
80
81
|
const normalizedTheme = normalizeTheme(theme);
|
|
81
82
|
const colors = useThemeColors(normalizedTheme);
|
|
82
83
|
const themeStyles = useThemeStyles(normalizedTheme);
|
|
84
|
+
const { t } = useI18n();
|
|
83
85
|
const styles = useMemo(() => createPaymentStyles(colors), [colors]);
|
|
84
86
|
|
|
85
87
|
// Determine if the payment is for a recurring item (subscription)
|
|
@@ -183,11 +185,11 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
|
|
|
183
185
|
if (!amount || Number.isNaN(Number(amount)) || Number(amount) <= 0) {
|
|
184
186
|
return (
|
|
185
187
|
<View style={styles.errorContainer}>
|
|
186
|
-
<Text style={styles.errorText}>
|
|
188
|
+
<Text style={styles.errorText}>{t('payment.errors.invalidAmount')}</Text>
|
|
187
189
|
<GroupedPillButtons
|
|
188
190
|
buttons={[
|
|
189
191
|
{
|
|
190
|
-
text: '
|
|
192
|
+
text: t('payment.actions.close'),
|
|
191
193
|
onPress: handleClose,
|
|
192
194
|
icon: 'close',
|
|
193
195
|
variant: 'primary',
|
|
@@ -20,6 +20,7 @@ import { Header, GroupedSection } from '../components';
|
|
|
20
20
|
import { useThemeStyles } from '../hooks/useThemeStyles';
|
|
21
21
|
import { normalizeTheme } from '../utils/themeUtils';
|
|
22
22
|
import { useOxy } from '../context/OxyContext';
|
|
23
|
+
import { useI18n } from '../hooks/useI18n';
|
|
23
24
|
|
|
24
25
|
// Button background colors for session actions
|
|
25
26
|
const SWITCH_BUTTON_BG = {
|
|
@@ -46,6 +47,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
46
47
|
logoutAll,
|
|
47
48
|
switchSession,
|
|
48
49
|
} = useOxy();
|
|
50
|
+
const { t } = useI18n();
|
|
49
51
|
const [loading, setLoading] = useState(true);
|
|
50
52
|
const [refreshing, setRefreshing] = useState(false);
|
|
51
53
|
const [actionLoading, setActionLoading] = useState<string | null>(null);
|
|
@@ -74,11 +76,11 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
74
76
|
console.error('Failed to load sessions:', error);
|
|
75
77
|
}
|
|
76
78
|
if (Platform.OS === 'web') {
|
|
77
|
-
toast.error('
|
|
79
|
+
toast.error(t('sessionManagement.toasts.loadFailed'));
|
|
78
80
|
} else {
|
|
79
81
|
Alert.alert(
|
|
80
82
|
'Error',
|
|
81
|
-
'
|
|
83
|
+
t('sessionManagement.toasts.loadFailed'),
|
|
82
84
|
[{ text: 'OK' }]
|
|
83
85
|
);
|
|
84
86
|
}
|
|
@@ -90,17 +92,17 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
90
92
|
|
|
91
93
|
// Memoized logout session handler - prevents unnecessary re-renders
|
|
92
94
|
const handleLogoutSession = useCallback(async (sessionId: string) => {
|
|
93
|
-
confirmAction('
|
|
95
|
+
confirmAction(t('sessionManagement.confirms.logoutSession'), async () => {
|
|
94
96
|
try {
|
|
95
97
|
setActionLoading(sessionId);
|
|
96
98
|
await logout(sessionId);
|
|
97
99
|
await refreshSessions();
|
|
98
|
-
toast.success('
|
|
100
|
+
toast.success(t('sessionManagement.toasts.logoutSuccess'));
|
|
99
101
|
} catch (error) {
|
|
100
102
|
if (__DEV__) {
|
|
101
103
|
console.error('Logout session failed:', error);
|
|
102
104
|
}
|
|
103
|
-
toast.error('
|
|
105
|
+
toast.error(t('sessionManagement.toasts.logoutFailed'));
|
|
104
106
|
} finally {
|
|
105
107
|
setActionLoading(null);
|
|
106
108
|
}
|
|
@@ -116,11 +118,11 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
116
118
|
// Memoized logout other sessions handler - prevents unnecessary re-renders
|
|
117
119
|
const handleLogoutOtherSessions = useCallback(async () => {
|
|
118
120
|
if (otherSessionsCount === 0) {
|
|
119
|
-
toast.info('
|
|
121
|
+
toast.info(t('sessionManagement.toasts.noOtherSessions'));
|
|
120
122
|
return;
|
|
121
123
|
}
|
|
122
124
|
confirmAction(
|
|
123
|
-
|
|
125
|
+
t('sessionManagement.confirms.logoutOthers', { count: otherSessionsCount }),
|
|
124
126
|
async () => {
|
|
125
127
|
try {
|
|
126
128
|
setActionLoading('others');
|
|
@@ -130,12 +132,12 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
134
|
await refreshSessions();
|
|
133
|
-
toast.success('
|
|
135
|
+
toast.success(t('sessionManagement.toasts.logoutOthersSuccess'));
|
|
134
136
|
} catch (error) {
|
|
135
137
|
if (__DEV__) {
|
|
136
138
|
console.error('Logout other sessions failed:', error);
|
|
137
139
|
}
|
|
138
|
-
toast.error('
|
|
140
|
+
toast.error(t('sessionManagement.toasts.logoutOthersFailed'));
|
|
139
141
|
} finally {
|
|
140
142
|
setActionLoading(null);
|
|
141
143
|
}
|
|
@@ -146,7 +148,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
146
148
|
// Memoized logout all sessions handler - prevents unnecessary re-renders
|
|
147
149
|
const handleLogoutAllSessions = useCallback(async () => {
|
|
148
150
|
confirmAction(
|
|
149
|
-
'
|
|
151
|
+
t('sessionManagement.confirms.logoutAll'),
|
|
150
152
|
async () => {
|
|
151
153
|
try {
|
|
152
154
|
setActionLoading('all');
|
|
@@ -155,7 +157,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
155
157
|
if (__DEV__) {
|
|
156
158
|
console.error('Logout all sessions failed:', error);
|
|
157
159
|
}
|
|
158
|
-
toast.error('
|
|
160
|
+
toast.error(t('sessionManagement.toasts.logoutAllFailed'));
|
|
159
161
|
} finally {
|
|
160
162
|
setActionLoading(null);
|
|
161
163
|
}
|
|
@@ -165,7 +167,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
165
167
|
|
|
166
168
|
// Memoized relative time formatter - prevents function recreation on every render
|
|
167
169
|
const formatRelative = useCallback((dateString?: string) => {
|
|
168
|
-
if (!dateString) return '
|
|
170
|
+
if (!dateString) return t('appInfo.items.unknown');
|
|
169
171
|
const date = new Date(dateString);
|
|
170
172
|
const now = new Date();
|
|
171
173
|
const diffMs = date.getTime() - now.getTime();
|
|
@@ -187,12 +189,12 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
187
189
|
setSwitchLoading(sessionId);
|
|
188
190
|
try {
|
|
189
191
|
await switchSession(sessionId);
|
|
190
|
-
toast.success('
|
|
192
|
+
toast.success(t('sessionManagement.toasts.switchSuccess'));
|
|
191
193
|
} catch (e) {
|
|
192
194
|
if (__DEV__) {
|
|
193
195
|
console.error('Switch session failed', e);
|
|
194
196
|
}
|
|
195
|
-
toast.error('
|
|
197
|
+
toast.error(t('sessionManagement.toasts.switchFailed'));
|
|
196
198
|
} finally {
|
|
197
199
|
setSwitchLoading(null);
|
|
198
200
|
}
|
|
@@ -220,7 +222,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
220
222
|
id: session.sessionId,
|
|
221
223
|
icon: isCurrent ? 'shield-checkmark' : 'laptop-outline',
|
|
222
224
|
iconColor: isCurrent ? successColor : primaryColor,
|
|
223
|
-
title: isCurrent ? '
|
|
225
|
+
title: isCurrent ? t('sessionManagement.currentSession') : t('sessionManagement.sessionLabel', { id: session.sessionId.substring(0, 8) }),
|
|
224
226
|
subtitle: subtitleParts.join(' \u2022 '),
|
|
225
227
|
showChevron: false,
|
|
226
228
|
multiRow: true,
|
|
@@ -234,7 +236,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
234
236
|
{switchLoading === session.sessionId ? (
|
|
235
237
|
<ActivityIndicator size="small" color={primaryColor} />
|
|
236
238
|
) : (
|
|
237
|
-
<Text style={[styles.sessionPillText, { color: primaryColor }]}>
|
|
239
|
+
<Text style={[styles.sessionPillText, { color: primaryColor }]}>{t('sessionManagement.switch')}</Text>
|
|
238
240
|
)}
|
|
239
241
|
</TouchableOpacity>
|
|
240
242
|
<TouchableOpacity
|
|
@@ -245,13 +247,13 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
245
247
|
{actionLoading === session.sessionId ? (
|
|
246
248
|
<ActivityIndicator size="small" color={dangerColor} />
|
|
247
249
|
) : (
|
|
248
|
-
<Text style={[styles.sessionPillText, { color: dangerColor }]}>
|
|
250
|
+
<Text style={[styles.sessionPillText, { color: dangerColor }]}>{t('sessionManagement.logout')}</Text>
|
|
249
251
|
)}
|
|
250
252
|
</TouchableOpacity>
|
|
251
253
|
</View>
|
|
252
254
|
) : (
|
|
253
255
|
<View style={styles.sessionActionsRow}>
|
|
254
|
-
<Text style={[styles.currentBadgeText, { color: successColor }]}>
|
|
256
|
+
<Text style={[styles.currentBadgeText, { color: successColor }]}>{t('sessionManagement.active')}</Text>
|
|
255
257
|
</View>
|
|
256
258
|
),
|
|
257
259
|
selected: isCurrent,
|
|
@@ -265,8 +267,8 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
265
267
|
id: 'logout-others',
|
|
266
268
|
icon: 'exit-outline',
|
|
267
269
|
iconColor: primaryColor,
|
|
268
|
-
title: '
|
|
269
|
-
subtitle: otherSessionsCount === 0 ? '
|
|
270
|
+
title: t('sessionManagement.logoutOthers.title'),
|
|
271
|
+
subtitle: otherSessionsCount === 0 ? t('sessionManagement.logoutOthers.noOtherSessions') : t('sessionManagement.logoutOthers.subtitle'),
|
|
270
272
|
onPress: handleLogoutOtherSessions,
|
|
271
273
|
showChevron: false,
|
|
272
274
|
customContent: actionLoading === 'others' ? <ActivityIndicator size="small" color={primaryColor} /> : undefined,
|
|
@@ -277,8 +279,8 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
277
279
|
id: 'logout-all',
|
|
278
280
|
icon: 'warning-outline',
|
|
279
281
|
iconColor: dangerColor,
|
|
280
|
-
title: '
|
|
281
|
-
subtitle: '
|
|
282
|
+
title: t('sessionManagement.logoutAll.title'),
|
|
283
|
+
subtitle: t('sessionManagement.logoutAll.subtitle'),
|
|
282
284
|
onPress: handleLogoutAllSessions,
|
|
283
285
|
showChevron: false,
|
|
284
286
|
customContent: actionLoading === 'all' ? <ActivityIndicator size="small" color={dangerColor} /> : undefined,
|
|
@@ -291,7 +293,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
291
293
|
return (
|
|
292
294
|
<View style={[styles.container, styles.centerContent, { backgroundColor }]}>
|
|
293
295
|
<ActivityIndicator size="large" color={primaryColor} />
|
|
294
|
-
<Text style={[styles.loadingText, { color: textColor }]}>
|
|
296
|
+
<Text style={[styles.loadingText, { color: textColor }]}>{t('sessionManagement.loading')}</Text>
|
|
295
297
|
</View>
|
|
296
298
|
);
|
|
297
299
|
}
|
|
@@ -299,8 +301,8 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
299
301
|
return (
|
|
300
302
|
<View style={[styles.container, { backgroundColor }]}>
|
|
301
303
|
<Header
|
|
302
|
-
title=
|
|
303
|
-
subtitle=
|
|
304
|
+
title={t('sessionManagement.title')}
|
|
305
|
+
subtitle={t('sessionManagement.subtitle')}
|
|
304
306
|
|
|
305
307
|
onBack={goBack || onClose}
|
|
306
308
|
elevation="subtle"
|
|
@@ -319,7 +321,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
319
321
|
{userSessions.length > 0 ? (
|
|
320
322
|
<>
|
|
321
323
|
{lastRefreshed && (
|
|
322
|
-
<Text style={[styles.metaText, { color: '#777', marginBottom: 6 }]}>
|
|
324
|
+
<Text style={[styles.metaText, { color: '#777', marginBottom: 6 }]}>{t('sessionManagement.lastRefreshed', { time: formatRelative(lastRefreshed.toISOString()) })}</Text>
|
|
323
325
|
)}
|
|
324
326
|
<View style={styles.fullBleed}>
|
|
325
327
|
<GroupedSection items={sessionItems} />
|
|
@@ -331,13 +333,13 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
331
333
|
</>
|
|
332
334
|
) : (
|
|
333
335
|
<View style={styles.emptyState}>
|
|
334
|
-
<Text style={[styles.emptyStateText, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
|
|
336
|
+
<Text style={[styles.emptyStateText, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>{t('sessionManagement.empty')}</Text>
|
|
335
337
|
</View>
|
|
336
338
|
)}
|
|
337
339
|
</ScrollView>
|
|
338
340
|
<View style={[styles.footer, { borderTopColor: borderColor }]}>
|
|
339
341
|
<TouchableOpacity style={styles.closeButton} onPress={onClose}>
|
|
340
|
-
<Text style={[styles.closeButtonText, { color: primaryColor }]}>
|
|
342
|
+
<Text style={[styles.closeButtonText, { color: primaryColor }]}>{t('sessionManagement.close')}</Text>
|
|
341
343
|
</TouchableOpacity>
|
|
342
344
|
</View>
|
|
343
345
|
</View>
|
|
@@ -5,6 +5,7 @@ import type { BaseScreenProps } from '../types/navigation';
|
|
|
5
5
|
import { Header, GroupedSection } from '../components';
|
|
6
6
|
import { useThemeStyles } from '../hooks/useThemeStyles';
|
|
7
7
|
import { normalizeTheme } from '../utils/themeUtils';
|
|
8
|
+
import { useI18n } from '../hooks/useI18n';
|
|
8
9
|
|
|
9
10
|
interface UserLinksScreenProps extends BaseScreenProps {
|
|
10
11
|
userId: string;
|
|
@@ -28,6 +29,7 @@ const UserLinksScreen: React.FC<UserLinksScreenProps> = ({
|
|
|
28
29
|
// primaryColor from hook (#007AFF) is already correct for this screen
|
|
29
30
|
const normalizedTheme = normalizeTheme(theme);
|
|
30
31
|
const themeStyles = useThemeStyles(normalizedTheme);
|
|
32
|
+
const { t } = useI18n();
|
|
31
33
|
|
|
32
34
|
const handleLinkPress = async (url: string) => {
|
|
33
35
|
try {
|
|
@@ -54,15 +56,15 @@ const UserLinksScreen: React.FC<UserLinksScreenProps> = ({
|
|
|
54
56
|
return (
|
|
55
57
|
<View style={[styles.container, { backgroundColor: themeStyles.backgroundColor }]}>
|
|
56
58
|
<Header
|
|
57
|
-
title=
|
|
58
|
-
subtitle={
|
|
59
|
+
title={t('userLinks.title')}
|
|
60
|
+
subtitle={links.length !== 1 ? t('userLinks.linkCount_plural', { count: links.length }) : t('userLinks.linkCount', { count: links.length })}
|
|
59
61
|
onBack={goBack}
|
|
60
62
|
elevation="subtle"
|
|
61
63
|
/>
|
|
62
64
|
|
|
63
65
|
<ScrollView style={styles.content}>
|
|
64
66
|
<View style={styles.section}>
|
|
65
|
-
<Text style={[styles.sectionTitle, { color: themeStyles.textColor }]}>
|
|
67
|
+
<Text style={[styles.sectionTitle, { color: themeStyles.textColor }]}>{t('userLinks.title')}</Text>
|
|
66
68
|
|
|
67
69
|
<GroupedSection
|
|
68
70
|
items={groupedItems}
|
|
@@ -164,8 +164,8 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
164
164
|
if (avatarStepIndex >= 0 && currentStep !== avatarStepIndex) {
|
|
165
165
|
animateToStepCallback(avatarStepIndex);
|
|
166
166
|
}
|
|
167
|
-
} catch (e:
|
|
168
|
-
toast.error(e.message || t('editProfile.toasts.updateAvatarFailed') || 'Failed to update avatar');
|
|
167
|
+
} catch (e: unknown) {
|
|
168
|
+
toast.error((e instanceof Error ? e.message : null) || t('editProfile.toasts.updateAvatarFailed') || 'Failed to update avatar');
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
});
|
|
@@ -29,7 +29,7 @@ const KarmaLeaderboardScreen: React.FC<BaseScreenProps> = ({ goBack, theme, navi
|
|
|
29
29
|
setError(null);
|
|
30
30
|
oxyServices.getKarmaLeaderboard()
|
|
31
31
|
.then((data: any) => setLeaderboard(Array.isArray(data) ? data : []))
|
|
32
|
-
.catch((err:
|
|
32
|
+
.catch((err: unknown) => setError((err instanceof Error ? err.message : null) || 'Failed to load leaderboard'))
|
|
33
33
|
.finally(() => setIsLoading(false));
|
|
34
34
|
}, [oxyServices]);
|
|
35
35
|
|
|
@@ -28,7 +28,7 @@ const KarmaRulesScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
|
|
|
28
28
|
setError(null);
|
|
29
29
|
oxyServices.getKarmaRules()
|
|
30
30
|
.then((data: any) => setRules(Array.isArray(data) ? data : []))
|
|
31
|
-
.catch((err:
|
|
31
|
+
.catch((err: unknown) => setError((err instanceof Error ? err.message : null) || 'Failed to load rules'))
|
|
32
32
|
.finally(() => setIsLoading(false));
|
|
33
33
|
}, [oxyServices]);
|
|
34
34
|
|
|
@@ -59,10 +59,10 @@ export const useFollowStore = create<FollowState>((set: any, get: any) => ({
|
|
|
59
59
|
fetchingUsers: { ...state.fetchingUsers, [userId]: false },
|
|
60
60
|
errors: { ...state.errors, [userId]: null },
|
|
61
61
|
}));
|
|
62
|
-
} catch (error:
|
|
62
|
+
} catch (error: unknown) {
|
|
63
63
|
set((state: FollowState) => ({
|
|
64
64
|
fetchingUsers: { ...state.fetchingUsers, [userId]: false },
|
|
65
|
-
errors: { ...state.errors, [userId]: error
|
|
65
|
+
errors: { ...state.errors, [userId]: (error instanceof Error ? error.message : null) || 'Failed to fetch follow status' },
|
|
66
66
|
}));
|
|
67
67
|
}
|
|
68
68
|
},
|
|
@@ -119,10 +119,10 @@ export const useFollowStore = create<FollowState>((set: any, get: any) => ({
|
|
|
119
119
|
return updates;
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
|
-
} catch (error:
|
|
122
|
+
} catch (error: unknown) {
|
|
123
123
|
set((state: FollowState) => ({
|
|
124
124
|
loadingUsers: { ...state.loadingUsers, [userId]: false },
|
|
125
|
-
errors: { ...state.errors, [userId]: error
|
|
125
|
+
errors: { ...state.errors, [userId]: (error instanceof Error ? error.message : null) || 'Failed to update follow status' },
|
|
126
126
|
}));
|
|
127
127
|
}
|
|
128
128
|
},
|
|
@@ -56,6 +56,8 @@ export interface OxyProviderProps {
|
|
|
56
56
|
authWebUrl?: string;
|
|
57
57
|
authRedirectUri?: string;
|
|
58
58
|
queryClient?: QueryClient;
|
|
59
|
+
/** Skip wrapping in SafeAreaProvider/GestureHandlerRootView (use when parent already provides them) */
|
|
60
|
+
skipProviderWrappers?: boolean;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
|
|
@@ -54,7 +54,7 @@ export const isInvalidSessionError = (error: unknown): boolean => {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// Check error.status directly (HttpService sets this)
|
|
57
|
-
if ((error as
|
|
57
|
+
if ('status' in (error as object) && (error as Record<string, unknown>).status === 401) {
|
|
58
58
|
return true;
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -83,7 +83,7 @@ export const isTimeoutOrNetworkError = (error: unknown): boolean => {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
const message = extractErrorMessage(error, '').toLowerCase();
|
|
86
|
-
const errorCode = (error as
|
|
86
|
+
const errorCode = isObject(error) && 'code' in (error as object) ? (error as Record<string, unknown>).code : undefined;
|
|
87
87
|
|
|
88
88
|
// Check for timeout/cancelled messages
|
|
89
89
|
if (
|
|
@@ -82,6 +82,7 @@ export async function convertDocumentPickerAssetToFile(
|
|
|
82
82
|
}
|
|
83
83
|
// Preserve URI for preview if available (useful for mobile previews)
|
|
84
84
|
if (doc.uri) {
|
|
85
|
+
// biome-ignore lint/suspicious/noExplicitAny: attaching uri for mobile preview on a File object requires dynamic property assignment
|
|
85
86
|
(file as any).uri = doc.uri;
|
|
86
87
|
}
|
|
87
88
|
return file;
|
|
@@ -102,6 +103,7 @@ export async function convertDocumentPickerAssetToFile(
|
|
|
102
103
|
const fileType = doc.mimeType || blob.type || 'application/octet-stream';
|
|
103
104
|
file = new globalThis.File([blob], fileName, { type: fileType });
|
|
104
105
|
// Preserve URI for preview
|
|
106
|
+
// biome-ignore lint/suspicious/noExplicitAny: attaching uri for mobile preview on a File object requires dynamic property assignment
|
|
105
107
|
(file as any).uri = doc.uri;
|
|
106
108
|
return file;
|
|
107
109
|
}
|
|
@@ -110,7 +112,7 @@ export async function convertDocumentPickerAssetToFile(
|
|
|
110
112
|
// React Native's Blob doesn't support Uint8Array directly, so we use fetch
|
|
111
113
|
const fileName = doc.name || `file-${index + 1}`;
|
|
112
114
|
const fileType = doc.mimeType || 'application/octet-stream';
|
|
113
|
-
|
|
115
|
+
|
|
114
116
|
// Use fetch to get the file as a blob (works with file:// and content:// URIs in React Native)
|
|
115
117
|
const response = await fetch(doc.uri);
|
|
116
118
|
if (!response.ok) {
|
|
@@ -119,17 +121,18 @@ export async function convertDocumentPickerAssetToFile(
|
|
|
119
121
|
const blob = await response.blob();
|
|
120
122
|
file = new globalThis.File([blob], fileName, { type: fileType });
|
|
121
123
|
// Preserve URI for preview (especially important for mobile)
|
|
124
|
+
// biome-ignore lint/suspicious/noExplicitAny: attaching uri for mobile preview on a File object requires dynamic property assignment
|
|
122
125
|
(file as any).uri = doc.uri;
|
|
123
126
|
return file;
|
|
124
|
-
} catch (error:
|
|
127
|
+
} catch (error: unknown) {
|
|
125
128
|
console.error('Failed to read file from URI:', error);
|
|
126
|
-
throw new Error(`Failed to load file: ${error.message || 'Unknown error'}`);
|
|
129
|
+
throw new Error(`Failed to load file: ${(error instanceof Error ? error.message : null) || 'Unknown error'}`);
|
|
127
130
|
}
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
// No file or URI available - this shouldn't happen with Expo 54
|
|
131
134
|
throw new Error('Missing file data (no file or uri property)');
|
|
132
|
-
} catch (error:
|
|
135
|
+
} catch (error: unknown) {
|
|
133
136
|
console.error('Error converting document to file:', error);
|
|
134
137
|
throw error;
|
|
135
138
|
}
|
|
@@ -185,6 +188,7 @@ export function getSafeDownloadUrl(
|
|
|
185
188
|
export async function uploadFileRaw(
|
|
186
189
|
file: File | Blob,
|
|
187
190
|
userId: string,
|
|
191
|
+
// biome-ignore lint/suspicious/noExplicitAny: OxyServices type cannot be fully resolved due to mixin composition pattern
|
|
188
192
|
oxyServices: any,
|
|
189
193
|
visibility?: 'private' | 'public' | 'unlisted'
|
|
190
194
|
) {
|
|
@@ -198,10 +202,11 @@ export interface AvatarPickerConfig {
|
|
|
198
202
|
/** Navigation function from BaseScreenProps */
|
|
199
203
|
navigate?: (screen: RouteName, props?: Record<string, unknown>) => void;
|
|
200
204
|
/** OxyServices instance */
|
|
205
|
+
// biome-ignore lint/suspicious/noExplicitAny: OxyServices type cannot be fully resolved due to mixin composition pattern
|
|
201
206
|
oxyServices: any;
|
|
202
207
|
/** TanStack Query mutation for updating profile */
|
|
203
208
|
updateProfileMutation: {
|
|
204
|
-
mutateAsync: (updates: { avatar: string }) => Promise<
|
|
209
|
+
mutateAsync: (updates: { avatar: string }) => Promise<unknown>;
|
|
205
210
|
};
|
|
206
211
|
/** Callback to update local avatar state */
|
|
207
212
|
onAvatarSelected?: (fileId: string) => void;
|
|
@@ -257,7 +262,7 @@ export function createAvatarPickerHandler(config: AvatarPickerConfig): () => voi
|
|
|
257
262
|
multiSelect: false,
|
|
258
263
|
disabledMimeTypes: ['video/', 'audio/', 'application/pdf'],
|
|
259
264
|
afterSelect: 'none', // Don't navigate away - stay on current screen
|
|
260
|
-
onSelect: async (file:
|
|
265
|
+
onSelect: async (file: FileMetadata) => {
|
|
261
266
|
if (!file.contentType.startsWith('image/')) {
|
|
262
267
|
toast.error(t('editProfile.toasts.selectImage') || 'Please select an image file');
|
|
263
268
|
return;
|
|
@@ -276,8 +281,8 @@ export function createAvatarPickerHandler(config: AvatarPickerConfig): () => voi
|
|
|
276
281
|
await updateProfileMutation.mutateAsync({ avatar: file.id });
|
|
277
282
|
|
|
278
283
|
toast.success(t('editProfile.toasts.avatarUpdated') || 'Avatar updated');
|
|
279
|
-
} catch (e:
|
|
280
|
-
toast.error(e.message || t('editProfile.toasts.updateAvatarFailed') || 'Failed to update avatar');
|
|
284
|
+
} catch (e: unknown) {
|
|
285
|
+
toast.error((e instanceof Error ? e.message : null) || t('editProfile.toasts.updateAvatarFailed') || 'Failed to update avatar');
|
|
281
286
|
}
|
|
282
287
|
}
|
|
283
288
|
});
|
|
@@ -13,10 +13,11 @@ interface DeviceSession {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Service type for session helpers.
|
|
16
|
-
* Uses '
|
|
16
|
+
* Uses 'unknown' to work around TypeScript mixin composition type inference issues.
|
|
17
17
|
* The OxyServices class has these methods but TypeScript can't see them due to the mixin pattern.
|
|
18
|
+
* Methods are accessed dynamically, so callers must pass a properly typed instance.
|
|
18
19
|
*/
|
|
19
|
-
//
|
|
20
|
+
// biome-ignore lint/suspicious/noExplicitAny: OxyServices methods are accessed dynamically due to mixin composition; TypeScript cannot infer the full type
|
|
20
21
|
type OxyServicesAny = any;
|
|
21
22
|
|
|
22
23
|
export interface FetchSessionsWithFallbackOptions {
|