@oxyhq/services 6.9.5 → 6.9.7
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/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 +7 -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/StepBasedScreen.js +7 -2
- package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
- package/lib/commonjs/ui/components/TouchableRipple/Pressable.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/AnimatedButton.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/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/FeedbackScreen.js +2 -2
- package/lib/commonjs/ui/screens/FeedbackScreen.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/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/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 +7 -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/StepBasedScreen.js +7 -2
- package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
- package/lib/module/ui/components/TouchableRipple/Pressable.js.map +1 -1
- package/lib/module/ui/components/fileManagement/AnimatedButton.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/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/FeedbackScreen.js +2 -2
- package/lib/module/ui/screens/FeedbackScreen.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/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/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/StepBasedScreen.d.ts +5 -5
- package/lib/typescript/commonjs/ui/components/StepBasedScreen.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/TextField/types.d.ts +9 -9
- package/lib/typescript/commonjs/ui/components/TextField/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/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/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/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/StepBasedScreen.d.ts +5 -5
- package/lib/typescript/module/ui/components/StepBasedScreen.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/TextField/types.d.ts +9 -9
- package/lib/typescript/module/ui/components/TextField/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/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/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/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/StepBasedScreen.tsx +29 -19
- package/src/ui/components/TextField/Adornment/types.tsx +1 -1
- package/src/ui/components/TextField/types.tsx +14 -9
- package/src/ui/components/TouchableRipple/Pressable.tsx +1 -0
- package/src/ui/components/fileManagement/AnimatedButton.tsx +2 -2
- 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/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/FeedbackScreen.tsx +3 -3
- 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/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
|
@@ -72,13 +72,13 @@ export function useSettingToggle(options: UseSettingToggleOptions): UseSettingTo
|
|
|
72
72
|
if (showSuccessToast && successMessage) {
|
|
73
73
|
toast.success(successMessage);
|
|
74
74
|
}
|
|
75
|
-
} catch (err:
|
|
75
|
+
} catch (err: unknown) {
|
|
76
76
|
// Revert on error
|
|
77
77
|
if (revertOnError) {
|
|
78
78
|
setValue(previousValue);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
toast.error(errorMessage || err
|
|
81
|
+
toast.error(errorMessage || (err instanceof Error ? err.message : null) || 'An error occurred');
|
|
82
82
|
} finally {
|
|
83
83
|
setIsSaving(false);
|
|
84
84
|
}
|
|
@@ -122,7 +122,7 @@ export function useSettingToggles<T extends { [K in keyof T]: boolean }>(options
|
|
|
122
122
|
|
|
123
123
|
try {
|
|
124
124
|
await onSave(key, newValue);
|
|
125
|
-
} catch (err:
|
|
125
|
+
} catch (err: unknown) {
|
|
126
126
|
// Revert on error
|
|
127
127
|
if (revertOnError) {
|
|
128
128
|
setValues(prev => ({ ...prev, [key]: previousValue }));
|
|
@@ -131,7 +131,7 @@ export function useSettingToggles<T extends { [K in keyof T]: boolean }>(options
|
|
|
131
131
|
const message = typeof errorMessage === 'function'
|
|
132
132
|
? errorMessage(key)
|
|
133
133
|
: errorMessage;
|
|
134
|
-
toast.error(message || err
|
|
134
|
+
toast.error(message || (err instanceof Error ? err.message : null) || 'An error occurred');
|
|
135
135
|
} finally {
|
|
136
136
|
setSavingKeys(prev => {
|
|
137
137
|
const next = new Set(prev);
|
|
@@ -246,11 +246,11 @@ const AccountOverviewScreen: React.FC<BaseScreenProps> = ({
|
|
|
246
246
|
// For React Native, you'd need to use a library like expo-file-system
|
|
247
247
|
toast.success(t('accountOverview.items.downloadData.success') || 'Data downloaded successfully');
|
|
248
248
|
}
|
|
249
|
-
} catch (error:
|
|
249
|
+
} catch (error: unknown) {
|
|
250
250
|
if (__DEV__) {
|
|
251
251
|
console.error('Failed to download data:', error);
|
|
252
252
|
}
|
|
253
|
-
toast.error(error
|
|
253
|
+
toast.error((error instanceof Error ? error.message : null) || t('accountOverview.items.downloadData.error') || 'Failed to download data');
|
|
254
254
|
}
|
|
255
255
|
},
|
|
256
256
|
},
|
|
@@ -276,21 +276,21 @@ const AccountOverviewScreen: React.FC<BaseScreenProps> = ({
|
|
|
276
276
|
// For React Native, you'd need to use a library like expo-file-system
|
|
277
277
|
toast.success(t('accountOverview.items.downloadData.success') || 'Data downloaded successfully');
|
|
278
278
|
}
|
|
279
|
-
} catch (error:
|
|
279
|
+
} catch (error: unknown) {
|
|
280
280
|
if (__DEV__) {
|
|
281
281
|
console.error('Failed to download data:', error);
|
|
282
282
|
}
|
|
283
|
-
toast.error(error
|
|
283
|
+
toast.error((error instanceof Error ? error.message : null) || t('accountOverview.items.downloadData.error') || 'Failed to download data');
|
|
284
284
|
}
|
|
285
285
|
},
|
|
286
286
|
},
|
|
287
287
|
]
|
|
288
288
|
);
|
|
289
|
-
} catch (error:
|
|
289
|
+
} catch (error: unknown) {
|
|
290
290
|
if (__DEV__) {
|
|
291
291
|
console.error('Failed to initiate download:', error);
|
|
292
292
|
}
|
|
293
|
-
toast.error(error
|
|
293
|
+
toast.error((error instanceof Error ? error.message : null) || t('accountOverview.items.downloadData.error') || 'Failed to download data');
|
|
294
294
|
}
|
|
295
295
|
}, [oxyServices, user, t]);
|
|
296
296
|
|
|
@@ -70,12 +70,12 @@ const AccountVerificationScreen: React.FC<BaseScreenProps> = ({
|
|
|
70
70
|
},
|
|
71
71
|
]
|
|
72
72
|
);
|
|
73
|
-
} catch (error:
|
|
73
|
+
} catch (error: unknown) {
|
|
74
74
|
if (__DEV__) {
|
|
75
75
|
console.error('Failed to submit verification request:', error);
|
|
76
76
|
}
|
|
77
77
|
toast.error(
|
|
78
|
-
error
|
|
78
|
+
(error instanceof Error ? error.message : null) || t('accountVerification.submitError') || 'Failed to submit verification request'
|
|
79
79
|
);
|
|
80
80
|
} finally {
|
|
81
81
|
setIsSubmitting(false);
|
|
@@ -137,9 +137,9 @@ const FeedbackScreen: React.FC<BaseScreenProps> = ({
|
|
|
137
137
|
setCurrentStep(0);
|
|
138
138
|
}, 3000);
|
|
139
139
|
|
|
140
|
-
} catch (error:
|
|
141
|
-
setFeedbackState({ status: 'error', message: error.message || (t('feedback.toasts.submitFailed') || 'Failed to submit feedback') });
|
|
142
|
-
toast.error(error.message || (t('feedback.toasts.submitFailed') || 'Failed to submit feedback'));
|
|
140
|
+
} catch (error: unknown) {
|
|
141
|
+
setFeedbackState({ status: 'error', message: (error instanceof Error ? error.message : null) || (t('feedback.toasts.submitFailed') || 'Failed to submit feedback') });
|
|
142
|
+
toast.error((error instanceof Error ? error.message : null) || (t('feedback.toasts.submitFailed') || 'Failed to submit feedback'));
|
|
143
143
|
}
|
|
144
144
|
}, [feedbackData, user, isTypeStepValid, isDetailsStepValid, isContactStepValid, resetForm, setFeedbackState, t]);
|
|
145
145
|
|
|
@@ -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',
|
|
@@ -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 {
|
package/src/utils/hookUtils.ts
CHANGED
|
@@ -21,10 +21,11 @@ export function useAsync<T>(
|
|
|
21
21
|
const [loading, setLoading] = useState(false);
|
|
22
22
|
const [error, setError] = useState<Error | null>(null);
|
|
23
23
|
|
|
24
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: asyncFn is intentionally excluded — this is a mount-only pattern where the callback identity should not cause re-creation
|
|
24
25
|
const execute = useCallback(async () => {
|
|
25
26
|
setLoading(true);
|
|
26
27
|
setError(null);
|
|
27
|
-
|
|
28
|
+
|
|
28
29
|
try {
|
|
29
30
|
const result = await asyncFn();
|
|
30
31
|
setData(result);
|
|
@@ -52,9 +53,10 @@ export function useAsyncEffect<T>(
|
|
|
52
53
|
const [loading, setLoading] = useState(true);
|
|
53
54
|
const [error, setError] = useState<Error | null>(null);
|
|
54
55
|
|
|
56
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: asyncFn is intentionally excluded — this is a mount-only pattern where the callback identity should not trigger re-execution
|
|
55
57
|
useEffect(() => {
|
|
56
58
|
let mounted = true;
|
|
57
|
-
|
|
59
|
+
|
|
58
60
|
const execute = async () => {
|
|
59
61
|
try {
|
|
60
62
|
const result = await asyncFn();
|