@oxyhq/services 5.16.17 → 5.16.18
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/core/mixins/OxyServices.security.js +42 -0
- package/lib/commonjs/core/mixins/OxyServices.security.js.map +1 -1
- package/lib/commonjs/models/interfaces.js +2 -0
- package/lib/commonjs/models/interfaces.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +19 -1
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedItem.js +1 -27
- package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
- package/lib/commonjs/ui/components/Section.js +2 -1
- package/lib/commonjs/ui/components/Section.js.map +1 -1
- package/lib/commonjs/ui/components/SectionTitle.js +1 -2
- package/lib/commonjs/ui/components/SectionTitle.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/FileViewer.js +3 -3
- package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +44 -6
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +9 -2
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useDeviceManagement.js +1 -1
- package/lib/commonjs/ui/context/hooks/useLanguageManagement.js +1 -1
- package/lib/commonjs/ui/context/hooks/useSessionManagement.js +3 -3
- package/lib/commonjs/ui/context/hooks/useStorage.js +2 -2
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +1 -1
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +22 -7
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +13 -13
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +17 -17
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +2 -2
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +10 -9
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +15 -15
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +1 -1
- package/lib/commonjs/ui/screens/HelpSupportScreen.js +3 -3
- package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/HistoryViewScreen.js +2 -2
- package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +3 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LegalDocumentsScreen.js +4 -4
- package/lib/commonjs/ui/screens/LegalDocumentsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +1 -2
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ProfileScreen.js +44 -16
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +3 -1
- package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +2 -2
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +8 -5
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/commonjs/ui/utils/errorHandlers.js +49 -2
- package/lib/commonjs/ui/utils/errorHandlers.js.map +1 -1
- package/lib/commonjs/ui/utils/sessionHelpers.js +0 -2
- package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/commonjs/utils/languageUtils.js +11 -11
- package/lib/commonjs/utils/languageUtils.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.security.js +42 -0
- package/lib/module/core/mixins/OxyServices.security.js.map +1 -1
- package/lib/module/models/interfaces.js +2 -0
- package/lib/module/models/interfaces.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +19 -1
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/GroupedItem.js +1 -29
- package/lib/module/ui/components/GroupedItem.js.map +1 -1
- package/lib/module/ui/components/Section.js +2 -1
- package/lib/module/ui/components/Section.js.map +1 -1
- package/lib/module/ui/components/SectionTitle.js +1 -2
- package/lib/module/ui/components/SectionTitle.js.map +1 -1
- package/lib/module/ui/components/fileManagement/FileViewer.js +3 -3
- package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +45 -7
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +9 -2
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/hooks/useDeviceManagement.js +1 -1
- package/lib/module/ui/context/hooks/useDeviceManagement.js.map +1 -1
- package/lib/module/ui/context/hooks/useLanguageManagement.js +1 -1
- package/lib/module/ui/context/hooks/useLanguageManagement.js.map +1 -1
- package/lib/module/ui/context/hooks/useSessionManagement.js +3 -3
- package/lib/module/ui/context/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/context/hooks/useStorage.js +2 -2
- package/lib/module/ui/context/hooks/useStorage.js.map +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +22 -7
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +13 -13
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +17 -17
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +2 -2
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +11 -10
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +15 -15
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +1 -1
- package/lib/module/ui/screens/HelpSupportScreen.js +3 -3
- package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
- package/lib/module/ui/screens/HistoryViewScreen.js +2 -2
- package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +4 -2
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/module/ui/screens/LegalDocumentsScreen.js +4 -4
- package/lib/module/ui/screens/LegalDocumentsScreen.js.map +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js +1 -2
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +44 -16
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaAboutScreen.js +3 -1
- package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js +3 -3
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +9 -6
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/module/ui/utils/errorHandlers.js +46 -0
- package/lib/module/ui/utils/errorHandlers.js.map +1 -1
- package/lib/module/ui/utils/sessionHelpers.js +0 -2
- package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/module/utils/languageUtils.js +11 -11
- package/lib/module/utils/languageUtils.js.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.security.d.ts +12 -0
- package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +2 -0
- package/lib/typescript/core/mixins/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +1 -1
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
- package/lib/typescript/ui/components/Section.d.ts.map +1 -1
- package/lib/typescript/ui/components/SectionTitle.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts +1 -1
- package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts +1 -1
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useStorage.d.ts +1 -1
- package/lib/typescript/ui/context/hooks/useStorage.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/utils/errorHandlers.d.ts +5 -0
- package/lib/typescript/ui/utils/errorHandlers.d.ts.map +1 -1
- package/lib/typescript/ui/utils/sessionHelpers.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/mixins/OxyServices.security.ts +44 -0
- package/src/models/interfaces.ts +4 -0
- package/src/ui/components/FollowButton.tsx +19 -1
- package/src/ui/components/GroupedItem.tsx +1 -29
- package/src/ui/components/Section.tsx +1 -0
- package/src/ui/components/SectionTitle.tsx +0 -1
- package/src/ui/components/fileManagement/FileViewer.tsx +3 -3
- package/src/ui/context/OxyContext.tsx +30 -9
- package/src/ui/context/hooks/useAuthOperations.ts +16 -9
- package/src/ui/context/hooks/useDeviceManagement.ts +1 -1
- package/src/ui/context/hooks/useLanguageManagement.ts +2 -2
- package/src/ui/context/hooks/useSessionManagement.ts +3 -3
- package/src/ui/context/hooks/useStorage.ts +2 -2
- package/src/ui/hooks/queries/useAccountQueries.ts +1 -1
- package/src/ui/hooks/queries/useServicesQueries.ts +1 -1
- package/src/ui/hooks/useSessionSocket.ts +8 -7
- package/src/ui/screens/AccountCenterScreen.tsx +13 -13
- package/src/ui/screens/AccountOverviewScreen.tsx +17 -17
- package/src/ui/screens/AccountSettingsScreen.tsx +2 -2
- package/src/ui/screens/AccountSwitcherScreen.tsx +8 -8
- package/src/ui/screens/AppInfoScreen.tsx +15 -15
- package/src/ui/screens/FeedbackScreen.tsx +1 -1
- package/src/ui/screens/FileManagementScreen.tsx +1 -1
- package/src/ui/screens/HelpSupportScreen.tsx +3 -3
- package/src/ui/screens/HistoryViewScreen.tsx +2 -2
- package/src/ui/screens/LanguageSelectorScreen.tsx +4 -1
- package/src/ui/screens/LegalDocumentsScreen.tsx +4 -4
- package/src/ui/screens/PaymentGatewayScreen.tsx +1 -1
- package/src/ui/screens/PremiumSubscriptionScreen.tsx +0 -1
- package/src/ui/screens/ProfileScreen.tsx +61 -22
- package/src/ui/screens/SavesCollectionsScreen.tsx +10 -1
- package/src/ui/screens/karma/KarmaAboutScreen.tsx +8 -1
- package/src/ui/screens/karma/KarmaCenterScreen.tsx +2 -2
- package/src/ui/screens/karma/KarmaRewardsScreen.tsx +9 -6
- package/src/ui/utils/errorHandlers.ts +58 -0
- package/src/ui/utils/sessionHelpers.ts +0 -2
- package/src/utils/languageUtils.ts +11 -11
- package/lib/commonjs/ui/context/utils/errorHandlers.js +0 -100
- package/lib/commonjs/ui/context/utils/errorHandlers.js.map +0 -1
- package/lib/commonjs/ui/context/utils/sessionHelpers.js +0 -103
- package/lib/commonjs/ui/context/utils/sessionHelpers.js.map +0 -1
- package/lib/commonjs/ui/context/utils/storageHelpers.js +0 -119
- package/lib/commonjs/ui/context/utils/storageHelpers.js.map +0 -1
- package/lib/module/ui/context/utils/errorHandlers.js +0 -93
- package/lib/module/ui/context/utils/errorHandlers.js.map +0 -1
- package/lib/module/ui/context/utils/sessionHelpers.js +0 -96
- package/lib/module/ui/context/utils/sessionHelpers.js.map +0 -1
- package/lib/module/ui/context/utils/storageHelpers.js +0 -111
- package/lib/module/ui/context/utils/storageHelpers.js.map +0 -1
- package/lib/typescript/ui/context/utils/errorHandlers.d.ts +0 -30
- package/lib/typescript/ui/context/utils/errorHandlers.d.ts.map +0 -1
- package/lib/typescript/ui/context/utils/sessionHelpers.d.ts +0 -59
- package/lib/typescript/ui/context/utils/sessionHelpers.d.ts.map +0 -1
- package/lib/typescript/ui/context/utils/storageHelpers.d.ts +0 -31
- package/lib/typescript/ui/context/utils/storageHelpers.d.ts.map +0 -1
- package/src/ui/context/utils/errorHandlers.ts +0 -146
- package/src/ui/context/utils/sessionHelpers.ts +0 -146
- package/src/ui/context/utils/storageHelpers.ts +0 -134
|
@@ -2,23 +2,36 @@ import type React from 'react';
|
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { View, Text, StyleSheet, ActivityIndicator, ScrollView, TouchableOpacity, Image } from 'react-native';
|
|
4
4
|
import type { BaseScreenProps } from '../types/navigation';
|
|
5
|
-
import { useThemeColors } from '../styles';
|
|
5
|
+
import { useThemeColors, type ThemeColors } from '../styles';
|
|
6
6
|
import Avatar from '../components/Avatar';
|
|
7
7
|
import { FollowButton } from '../components';
|
|
8
8
|
import { useFollow } from '../hooks/useFollow';
|
|
9
9
|
import { Ionicons } from '@expo/vector-icons';
|
|
10
10
|
import { useI18n } from '../hooks/useI18n';
|
|
11
11
|
import { useOxy } from '../context/OxyContext';
|
|
12
|
+
import { logger } from '../../utils/loggerUtils';
|
|
13
|
+
import type { User } from '../../models/interfaces';
|
|
14
|
+
import { extractErrorMessage } from '../utils/errorHandlers';
|
|
12
15
|
|
|
13
16
|
interface ProfileScreenProps extends BaseScreenProps {
|
|
14
17
|
userId: string;
|
|
15
18
|
username?: string;
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
interface LinkMetadata {
|
|
22
|
+
id?: string;
|
|
23
|
+
url: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
image?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type ProfileLink = string | { link: string } | LinkMetadata;
|
|
30
|
+
|
|
18
31
|
const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme, goBack, navigate }) => {
|
|
19
32
|
// Use useOxy() hook for OxyContext values
|
|
20
33
|
const { oxyServices, user: currentUser } = useOxy();
|
|
21
|
-
const [profile, setProfile] = useState<
|
|
34
|
+
const [profile, setProfile] = useState<User | null>(null);
|
|
22
35
|
const [karmaTotal, setKarmaTotal] = useState<number | null>(null);
|
|
23
36
|
const [postsCount, setPostsCount] = useState<number | null>(null);
|
|
24
37
|
const [commentsCount, setCommentsCount] = useState<number | null>(null);
|
|
@@ -44,7 +57,15 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
44
57
|
const { t } = useI18n();
|
|
45
58
|
|
|
46
59
|
// Check if current user is viewing their own profile
|
|
47
|
-
|
|
60
|
+
// Normalize IDs by trimming whitespace to handle format mismatches
|
|
61
|
+
const normalizeId = (id: string | undefined | null): string => {
|
|
62
|
+
if (!id) return '';
|
|
63
|
+
return String(id).trim();
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const currentUserId = normalizeId(currentUser?.id);
|
|
67
|
+
const targetUserId = normalizeId(userId);
|
|
68
|
+
const isOwnProfile = currentUserId && targetUserId && currentUserId === targetUserId;
|
|
48
69
|
|
|
49
70
|
useEffect(() => {
|
|
50
71
|
if (!userId) {
|
|
@@ -58,9 +79,11 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
58
79
|
|
|
59
80
|
// Load user profile and karma total
|
|
60
81
|
Promise.all([
|
|
61
|
-
oxyServices.getUserById(userId).catch((err:
|
|
82
|
+
oxyServices.getUserById(userId).catch((err: unknown) => {
|
|
62
83
|
// If this is the current user and the API call fails, use current user data as fallback
|
|
63
|
-
|
|
84
|
+
const normalizedCurrentId = normalizeId(currentUser?.id);
|
|
85
|
+
const normalizedTargetId = normalizeId(userId);
|
|
86
|
+
if (normalizedCurrentId && normalizedTargetId && normalizedCurrentId === normalizedTargetId) {
|
|
64
87
|
return currentUser;
|
|
65
88
|
}
|
|
66
89
|
throw err;
|
|
@@ -72,18 +95,24 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
72
95
|
Promise.resolve({ total: undefined })
|
|
73
96
|
])
|
|
74
97
|
.then(([profileRes, karmaRes]) => {
|
|
98
|
+
if (!profileRes) {
|
|
99
|
+
setError('Profile data is not available');
|
|
100
|
+
setIsLoading(false);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
75
104
|
setProfile(profileRes);
|
|
76
105
|
setKarmaTotal(typeof karmaRes.total === 'number' ? karmaRes.total : null);
|
|
77
106
|
|
|
78
107
|
// Extract links from profile data
|
|
79
108
|
if (profileRes.linksMetadata && Array.isArray(profileRes.linksMetadata)) {
|
|
80
|
-
const linksWithIds = profileRes.linksMetadata.map((link:
|
|
109
|
+
const linksWithIds = profileRes.linksMetadata.map((link: LinkMetadata, index: number) => ({
|
|
81
110
|
...link,
|
|
82
111
|
id: link.id || `existing-${index}`
|
|
83
112
|
}));
|
|
84
113
|
setLinks(linksWithIds);
|
|
85
114
|
} else if (Array.isArray(profileRes.links)) {
|
|
86
|
-
const simpleLinks = profileRes.links.map((l:
|
|
115
|
+
const simpleLinks = profileRes.links.map((l: ProfileLink) => typeof l === 'string' ? l : (typeof l === 'object' && 'link' in l ? l.link : '')).filter(Boolean);
|
|
87
116
|
const linksWithMetadata = simpleLinks.map((url: string, index: number) => ({
|
|
88
117
|
url,
|
|
89
118
|
title: url.replace(/^https?:\/\//, '').replace(/\/$/, ''),
|
|
@@ -110,23 +139,29 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
110
139
|
setPostsCount(Math.floor(Math.random() * 50));
|
|
111
140
|
setCommentsCount(Math.floor(Math.random() * 100));
|
|
112
141
|
})
|
|
113
|
-
.catch((err:
|
|
114
|
-
|
|
142
|
+
.catch((err: unknown) => {
|
|
143
|
+
logger.error('Profile loading error', err instanceof Error ? err : new Error(String(err)), { component: 'ProfileScreen' });
|
|
115
144
|
// Provide user-friendly error messages based on the error type
|
|
116
145
|
let errorMessage = 'Failed to load profile';
|
|
117
146
|
|
|
118
|
-
|
|
119
|
-
|
|
147
|
+
// Type guard for error with status property
|
|
148
|
+
const errorWithStatus = err && typeof err === 'object' && 'status' in err ? err as { status?: number; message?: string } : null;
|
|
149
|
+
const errorMessageText = extractErrorMessage(err, '');
|
|
150
|
+
|
|
151
|
+
if (errorWithStatus?.status === 404 || errorMessageText.includes('not found') || errorMessageText.includes('Resource not found')) {
|
|
152
|
+
const normalizedCurrentId = normalizeId(currentUser?.id);
|
|
153
|
+
const normalizedTargetId = normalizeId(userId);
|
|
154
|
+
if (normalizedCurrentId && normalizedTargetId && normalizedCurrentId === normalizedTargetId) {
|
|
120
155
|
errorMessage = 'Unable to load your profile from the server. This may be due to a temporary service issue.';
|
|
121
156
|
} else {
|
|
122
157
|
errorMessage = 'This user profile could not be found or may have been removed.';
|
|
123
158
|
}
|
|
124
|
-
} else if (
|
|
159
|
+
} else if (errorWithStatus?.status === 403) {
|
|
125
160
|
errorMessage = 'You do not have permission to view this profile.';
|
|
126
|
-
} else if (
|
|
161
|
+
} else if (errorWithStatus?.status === 500) {
|
|
127
162
|
errorMessage = 'Server error occurred while loading the profile. Please try again later.';
|
|
128
|
-
} else if (
|
|
129
|
-
errorMessage =
|
|
163
|
+
} else if (errorMessageText) {
|
|
164
|
+
errorMessage = errorMessageText;
|
|
130
165
|
}
|
|
131
166
|
|
|
132
167
|
setError(errorMessage);
|
|
@@ -196,7 +231,9 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
196
231
|
|
|
197
232
|
onFollowChange={(isFollowing) => {
|
|
198
233
|
// The follow button will automatically update counts via Zustand
|
|
199
|
-
|
|
234
|
+
if (__DEV__) {
|
|
235
|
+
logger.debug(`Follow status changed: ${isFollowing}`, { component: 'ProfileScreen' });
|
|
236
|
+
}
|
|
200
237
|
}}
|
|
201
238
|
/>
|
|
202
239
|
)}
|
|
@@ -204,7 +241,9 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
204
241
|
</View>
|
|
205
242
|
{/* Profile Info */}
|
|
206
243
|
<View style={styles.header}>
|
|
207
|
-
<Text style={[styles.displayName, { color: colors.text }]}>
|
|
244
|
+
<Text style={[styles.displayName, { color: colors.text }]}>
|
|
245
|
+
{(profile && 'displayName' in profile && typeof profile.displayName === 'string' ? profile.displayName : null) || profile?.username || username || profile?.id || ''}
|
|
246
|
+
</Text>
|
|
208
247
|
{profile?.username && (
|
|
209
248
|
<Text style={[styles.subText, { color: colors.secondaryText }]}>@{profile.username}</Text>
|
|
210
249
|
)}
|
|
@@ -233,25 +272,25 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
233
272
|
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.website}</Text>
|
|
234
273
|
</View>
|
|
235
274
|
)}
|
|
236
|
-
{profile
|
|
275
|
+
{profile && 'company' in profile && typeof profile.company === 'string' && profile.company && (
|
|
237
276
|
<View style={styles.infoGridItem}>
|
|
238
277
|
<Ionicons name="business-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
239
278
|
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.company}</Text>
|
|
240
279
|
</View>
|
|
241
280
|
)}
|
|
242
|
-
{profile
|
|
281
|
+
{profile && 'jobTitle' in profile && typeof profile.jobTitle === 'string' && profile.jobTitle && (
|
|
243
282
|
<View style={styles.infoGridItem}>
|
|
244
283
|
<Ionicons name="briefcase-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
245
284
|
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.jobTitle}</Text>
|
|
246
285
|
</View>
|
|
247
286
|
)}
|
|
248
|
-
{profile
|
|
287
|
+
{profile && 'education' in profile && typeof profile.education === 'string' && profile.education && (
|
|
249
288
|
<View style={styles.infoGridItem}>
|
|
250
289
|
<Ionicons name="school-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
251
290
|
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.education}</Text>
|
|
252
291
|
</View>
|
|
253
292
|
)}
|
|
254
|
-
{profile
|
|
293
|
+
{profile && 'birthday' in profile && typeof profile.birthday === 'string' && profile.birthday && (
|
|
255
294
|
<View style={styles.infoGridItem}>
|
|
256
295
|
<Ionicons name="gift-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
257
296
|
<Text style={[styles.infoGridText, { color: colors.secondaryText }]}>
|
|
@@ -307,7 +346,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
307
346
|
);
|
|
308
347
|
};
|
|
309
348
|
|
|
310
|
-
const createStyles = (colors:
|
|
349
|
+
const createStyles = (colors: ThemeColors) => StyleSheet.create({
|
|
311
350
|
container: { flex: 1 },
|
|
312
351
|
scrollContainer: { alignItems: 'stretch', paddingBottom: 40 },
|
|
313
352
|
bannerContainer: { height: 160, backgroundColor: colors.primary + '20', position: 'relative', overflow: 'hidden' },
|
|
@@ -22,6 +22,15 @@ interface SavedItem {
|
|
|
22
22
|
url?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
interface Collection {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
itemCount?: number;
|
|
30
|
+
createdAt?: Date;
|
|
31
|
+
updatedAt?: Date;
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
const SavesCollectionsScreen: React.FC<BaseScreenProps> = ({
|
|
26
35
|
onClose,
|
|
27
36
|
theme,
|
|
@@ -31,7 +40,7 @@ const SavesCollectionsScreen: React.FC<BaseScreenProps> = ({
|
|
|
31
40
|
const { oxyServices, user } = useOxy();
|
|
32
41
|
const { t } = useI18n();
|
|
33
42
|
const [savedItems, setSavedItems] = useState<SavedItem[]>([]);
|
|
34
|
-
const [collections, setCollections] = useState<
|
|
43
|
+
const [collections, setCollections] = useState<Collection[]>([]);
|
|
35
44
|
const [isLoading, setIsLoading] = useState(true);
|
|
36
45
|
const [activeTab, setActiveTab] = useState<'saves' | 'collections'>('saves');
|
|
37
46
|
|
|
@@ -6,6 +6,7 @@ import { useI18n } from '../../hooks/useI18n';
|
|
|
6
6
|
import { useThemeStyles } from '../../hooks/useThemeStyles';
|
|
7
7
|
import { normalizeTheme } from '../../utils/themeUtils';
|
|
8
8
|
import { useColorScheme } from '../../hooks/use-color-scheme';
|
|
9
|
+
import { fontFamilies } from '../../styles/fonts';
|
|
9
10
|
|
|
10
11
|
const KarmaAboutScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
|
|
11
12
|
const { t } = useI18n();
|
|
@@ -61,7 +62,13 @@ const styles = StyleSheet.create({
|
|
|
61
62
|
marginBottom: 24,
|
|
62
63
|
},
|
|
63
64
|
contentContainer: { padding: 24, paddingTop: 20 },
|
|
64
|
-
section: {
|
|
65
|
+
section: {
|
|
66
|
+
fontSize: 18,
|
|
67
|
+
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
68
|
+
fontFamily: fontFamilies.phuduBold,
|
|
69
|
+
marginTop: 24,
|
|
70
|
+
marginBottom: 8
|
|
71
|
+
},
|
|
65
72
|
paragraph: { fontSize: 16, marginBottom: 12 },
|
|
66
73
|
});
|
|
67
74
|
|
|
@@ -223,8 +223,8 @@ const styles = StyleSheet.create({
|
|
|
223
223
|
},
|
|
224
224
|
sectionTitle: {
|
|
225
225
|
fontSize: 18,
|
|
226
|
-
fontWeight: '600',
|
|
227
|
-
|
|
226
|
+
fontWeight: Platform.OS === 'web' ? '600' : undefined,
|
|
227
|
+
fontFamily: fontFamilies.phuduSemiBold,
|
|
228
228
|
marginTop: 8,
|
|
229
229
|
alignSelf: 'flex-start',
|
|
230
230
|
marginLeft: 24,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { useMemo, useState, useEffect } from 'react';
|
|
3
|
-
import { View, Text, StyleSheet, ScrollView, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { View, Text, StyleSheet, ScrollView, TouchableOpacity, Platform } from 'react-native';
|
|
4
4
|
import type { BaseScreenProps } from '../../types/navigation';
|
|
5
5
|
import { Header } from '../../components';
|
|
6
6
|
import { Ionicons } from '@expo/vector-icons';
|
|
@@ -11,6 +11,7 @@ import { useColorScheme } from '../../hooks/use-color-scheme';
|
|
|
11
11
|
import { Colors } from '../../constants/theme';
|
|
12
12
|
import { useOxy } from '../../context/OxyContext';
|
|
13
13
|
import { darkenColor, lightenColor } from '../../utils/colorUtils';
|
|
14
|
+
import { fontFamilies } from '../../styles/fonts';
|
|
14
15
|
|
|
15
16
|
interface Achievement {
|
|
16
17
|
id: string;
|
|
@@ -82,7 +83,7 @@ const KarmaRewardsScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
|
|
|
82
83
|
name: t('karma.achievements.contributor') || 'Contributor',
|
|
83
84
|
description: t('karma.achievements.contributorDesc') || 'Reached 50 karma points',
|
|
84
85
|
category: 'contribution',
|
|
85
|
-
icon: '
|
|
86
|
+
icon: 'account-group',
|
|
86
87
|
iconColor: '#007AFF',
|
|
87
88
|
unlocked: karmaTotal >= 50,
|
|
88
89
|
rarity: 'common',
|
|
@@ -456,7 +457,8 @@ const styles = StyleSheet.create({
|
|
|
456
457
|
},
|
|
457
458
|
currentKarma: {
|
|
458
459
|
fontSize: 36,
|
|
459
|
-
fontWeight: 'bold',
|
|
460
|
+
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
461
|
+
fontFamily: fontFamilies.phuduBold,
|
|
460
462
|
marginBottom: 4,
|
|
461
463
|
},
|
|
462
464
|
achievementStats: {
|
|
@@ -464,7 +466,8 @@ const styles = StyleSheet.create({
|
|
|
464
466
|
},
|
|
465
467
|
achievementCount: {
|
|
466
468
|
fontSize: 36,
|
|
467
|
-
fontWeight: 'bold',
|
|
469
|
+
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
470
|
+
fontFamily: fontFamilies.phuduBold,
|
|
468
471
|
marginBottom: 4,
|
|
469
472
|
},
|
|
470
473
|
achievementCountLabel: {
|
|
@@ -492,8 +495,8 @@ const styles = StyleSheet.create({
|
|
|
492
495
|
},
|
|
493
496
|
sectionTitle: {
|
|
494
497
|
fontSize: 20,
|
|
495
|
-
fontWeight: '600',
|
|
496
|
-
|
|
498
|
+
fontWeight: Platform.OS === 'web' ? '600' : undefined,
|
|
499
|
+
fontFamily: fontFamilies.phuduSemiBold,
|
|
497
500
|
marginTop: 8,
|
|
498
501
|
},
|
|
499
502
|
achievementsGrid: {
|
|
@@ -53,16 +53,74 @@ export const isInvalidSessionError = (error: unknown): boolean => {
|
|
|
53
53
|
return false;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// Check error.status directly (HttpService sets this)
|
|
57
|
+
if ((error as any).status === 401) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
56
61
|
const normalizedMessage = extractErrorMessage(error)?.toLowerCase();
|
|
57
62
|
if (!normalizedMessage) {
|
|
58
63
|
return false;
|
|
59
64
|
}
|
|
60
65
|
|
|
66
|
+
// Check for HTTP 401 in message (HttpService creates errors with "HTTP 401:" format)
|
|
67
|
+
if (normalizedMessage.includes('http 401') || normalizedMessage.includes('401')) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
61
71
|
return DEFAULT_INVALID_SESSION_MESSAGES.some((msg) =>
|
|
62
72
|
normalizedMessage.includes(msg.toLowerCase()),
|
|
63
73
|
);
|
|
64
74
|
};
|
|
65
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Determine whether the error represents a timeout or network error.
|
|
78
|
+
* These are expected when the device is offline or has poor connectivity.
|
|
79
|
+
*/
|
|
80
|
+
export const isTimeoutOrNetworkError = (error: unknown): boolean => {
|
|
81
|
+
if (!isObject(error) && !(error instanceof Error)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const message = extractErrorMessage(error, '').toLowerCase();
|
|
86
|
+
const errorCode = (error as any).code;
|
|
87
|
+
|
|
88
|
+
// Check for timeout/cancelled messages
|
|
89
|
+
if (
|
|
90
|
+
message.includes('timeout') ||
|
|
91
|
+
message.includes('cancelled') ||
|
|
92
|
+
message.includes('econnaborted') ||
|
|
93
|
+
message.includes('aborted') ||
|
|
94
|
+
message.includes('request timeout or cancelled')
|
|
95
|
+
) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Check for timeout/network error codes
|
|
100
|
+
if (errorCode === 'TIMEOUT' || errorCode === 'NETWORK_ERROR' || errorCode === 'ECONNABORTED') {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Check for AbortError
|
|
105
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check for network-related TypeErrors
|
|
110
|
+
if (error instanceof TypeError) {
|
|
111
|
+
const typeErrorMessage = error.message.toLowerCase();
|
|
112
|
+
if (
|
|
113
|
+
typeErrorMessage.includes('fetch') ||
|
|
114
|
+
typeErrorMessage.includes('network') ||
|
|
115
|
+
typeErrorMessage.includes('failed to fetch')
|
|
116
|
+
) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return false;
|
|
122
|
+
};
|
|
123
|
+
|
|
66
124
|
/**
|
|
67
125
|
* Extract a consistent error message from unknown error shapes.
|
|
68
126
|
*
|
|
@@ -82,8 +82,6 @@ export const fetchSessionsWithFallback = async (
|
|
|
82
82
|
} catch (error) {
|
|
83
83
|
if (__DEV__ && logger) {
|
|
84
84
|
logger('Failed to get device sessions, falling back to user sessions', error);
|
|
85
|
-
} else if (__DEV__) {
|
|
86
|
-
console.warn('Failed to get device sessions, falling back to user sessions:', error);
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
const userSessions = await oxyServices.getSessionsBySessionId(sessionId);
|
|
@@ -19,7 +19,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
19
19
|
name: 'English',
|
|
20
20
|
nativeName: 'English',
|
|
21
21
|
flag: '🇺🇸',
|
|
22
|
-
icon: '
|
|
22
|
+
icon: 'translate',
|
|
23
23
|
color: '#007AFF',
|
|
24
24
|
},
|
|
25
25
|
{
|
|
@@ -27,7 +27,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
27
27
|
name: 'Spanish',
|
|
28
28
|
nativeName: 'Español',
|
|
29
29
|
flag: '🇪🇸',
|
|
30
|
-
icon: '
|
|
30
|
+
icon: 'translate',
|
|
31
31
|
color: '#FF3B30',
|
|
32
32
|
},
|
|
33
33
|
{
|
|
@@ -35,7 +35,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
35
35
|
name: 'Catalan',
|
|
36
36
|
nativeName: 'Català',
|
|
37
37
|
flag: '🇪🇸',
|
|
38
|
-
icon: '
|
|
38
|
+
icon: 'translate',
|
|
39
39
|
color: '#0CA678',
|
|
40
40
|
},
|
|
41
41
|
{
|
|
@@ -43,7 +43,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
43
43
|
name: 'French',
|
|
44
44
|
nativeName: 'Français',
|
|
45
45
|
flag: '🇫🇷',
|
|
46
|
-
icon: '
|
|
46
|
+
icon: 'translate',
|
|
47
47
|
color: '#5856D6',
|
|
48
48
|
},
|
|
49
49
|
{
|
|
@@ -51,7 +51,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
51
51
|
name: 'German',
|
|
52
52
|
nativeName: 'Deutsch',
|
|
53
53
|
flag: '🇩🇪',
|
|
54
|
-
icon: '
|
|
54
|
+
icon: 'translate',
|
|
55
55
|
color: '#FF9500',
|
|
56
56
|
},
|
|
57
57
|
{
|
|
@@ -59,7 +59,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
59
59
|
name: 'Italian',
|
|
60
60
|
nativeName: 'Italiano',
|
|
61
61
|
flag: '🇮🇹',
|
|
62
|
-
icon: '
|
|
62
|
+
icon: 'translate',
|
|
63
63
|
color: '#34C759',
|
|
64
64
|
},
|
|
65
65
|
{
|
|
@@ -67,7 +67,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
67
67
|
name: 'Portuguese',
|
|
68
68
|
nativeName: 'Português',
|
|
69
69
|
flag: '🇵🇹',
|
|
70
|
-
icon: '
|
|
70
|
+
icon: 'translate',
|
|
71
71
|
color: '#AF52DE',
|
|
72
72
|
},
|
|
73
73
|
{
|
|
@@ -75,7 +75,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
75
75
|
name: 'Japanese',
|
|
76
76
|
nativeName: '日本語',
|
|
77
77
|
flag: '🇯🇵',
|
|
78
|
-
icon: '
|
|
78
|
+
icon: 'translate',
|
|
79
79
|
color: '#FF2D92',
|
|
80
80
|
},
|
|
81
81
|
{
|
|
@@ -83,7 +83,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
83
83
|
name: 'Korean',
|
|
84
84
|
nativeName: '한국어',
|
|
85
85
|
flag: '🇰🇷',
|
|
86
|
-
icon: '
|
|
86
|
+
icon: 'translate',
|
|
87
87
|
color: '#32D74B',
|
|
88
88
|
},
|
|
89
89
|
{
|
|
@@ -91,7 +91,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
91
91
|
name: 'Chinese',
|
|
92
92
|
nativeName: '中文',
|
|
93
93
|
flag: '🇨🇳',
|
|
94
|
-
icon: '
|
|
94
|
+
icon: 'translate',
|
|
95
95
|
color: '#FF9F0A',
|
|
96
96
|
},
|
|
97
97
|
{
|
|
@@ -99,7 +99,7 @@ export const SUPPORTED_LANGUAGES: LanguageMetadata[] = [
|
|
|
99
99
|
name: 'Arabic',
|
|
100
100
|
nativeName: 'العربية',
|
|
101
101
|
flag: '🇸🇦',
|
|
102
|
-
icon: '
|
|
102
|
+
icon: 'translate',
|
|
103
103
|
color: '#30B0C7',
|
|
104
104
|
},
|
|
105
105
|
];
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.isInvalidSessionError = exports.handleAuthError = exports.extractErrorMessage = void 0;
|
|
7
|
-
const DEFAULT_INVALID_SESSION_MESSAGES = ['Invalid or expired session', 'Session is invalid', 'Session not found', 'Session expired'];
|
|
8
|
-
const isObject = value => typeof value === 'object' && value !== null;
|
|
9
|
-
const getResponseStatus = error => {
|
|
10
|
-
if (!isObject(error)) return undefined;
|
|
11
|
-
const response = error.response;
|
|
12
|
-
return response?.status;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Determine whether the error represents an invalid session condition.
|
|
17
|
-
* This centralizes 401 detection across different fetch clients.
|
|
18
|
-
*/
|
|
19
|
-
const isInvalidSessionError = error => {
|
|
20
|
-
const status = getResponseStatus(error);
|
|
21
|
-
if (status === 401) {
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
if (!isObject(error)) {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Check error.status directly (HttpService sets this)
|
|
29
|
-
if (error.status === 401) {
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
const normalizedMessage = extractErrorMessage(error)?.toLowerCase();
|
|
33
|
-
if (!normalizedMessage) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Check for HTTP 401 in message (HttpService creates errors with "HTTP 401:" format)
|
|
38
|
-
if (normalizedMessage.includes('http 401') || normalizedMessage.includes('401')) {
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
return DEFAULT_INVALID_SESSION_MESSAGES.some(msg => normalizedMessage.includes(msg.toLowerCase()));
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Extract a consistent error message from unknown error shapes.
|
|
46
|
-
*
|
|
47
|
-
* @param error - The unknown error payload
|
|
48
|
-
* @param fallbackMessage - Message to return when no concrete message is available
|
|
49
|
-
*/
|
|
50
|
-
exports.isInvalidSessionError = isInvalidSessionError;
|
|
51
|
-
const extractErrorMessage = (error, fallbackMessage = 'Unexpected error') => {
|
|
52
|
-
if (typeof error === 'string' && error.trim().length > 0) {
|
|
53
|
-
return error;
|
|
54
|
-
}
|
|
55
|
-
if (!isObject(error)) {
|
|
56
|
-
return fallbackMessage;
|
|
57
|
-
}
|
|
58
|
-
const withMessage = error;
|
|
59
|
-
if (withMessage.message && withMessage.message.trim().length > 0) {
|
|
60
|
-
return withMessage.message;
|
|
61
|
-
}
|
|
62
|
-
const withResponse = error;
|
|
63
|
-
const responseMessage = withResponse.response?.data?.message ?? withResponse.response?.data?.error;
|
|
64
|
-
if (typeof responseMessage === 'string' && responseMessage.trim().length > 0) {
|
|
65
|
-
return responseMessage;
|
|
66
|
-
}
|
|
67
|
-
return fallbackMessage;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Centralized error handler for auth-related operations.
|
|
72
|
-
*
|
|
73
|
-
* @param error - Unknown error object
|
|
74
|
-
* @param options - Error handling configuration
|
|
75
|
-
* @returns Resolved error message
|
|
76
|
-
*/
|
|
77
|
-
exports.extractErrorMessage = extractErrorMessage;
|
|
78
|
-
const handleAuthError = (error, {
|
|
79
|
-
defaultMessage,
|
|
80
|
-
code,
|
|
81
|
-
status,
|
|
82
|
-
onError,
|
|
83
|
-
setAuthError,
|
|
84
|
-
logger
|
|
85
|
-
}) => {
|
|
86
|
-
const resolvedStatus = status ?? getResponseStatus(error) ?? (isInvalidSessionError(error) ? 401 : 500);
|
|
87
|
-
const message = extractErrorMessage(error, defaultMessage);
|
|
88
|
-
if (logger) {
|
|
89
|
-
logger(message, error);
|
|
90
|
-
}
|
|
91
|
-
setAuthError?.(message);
|
|
92
|
-
onError?.({
|
|
93
|
-
message,
|
|
94
|
-
code,
|
|
95
|
-
status: resolvedStatus
|
|
96
|
-
});
|
|
97
|
-
return message;
|
|
98
|
-
};
|
|
99
|
-
exports.handleAuthError = handleAuthError;
|
|
100
|
-
//# sourceMappingURL=errorHandlers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["DEFAULT_INVALID_SESSION_MESSAGES","isObject","value","getResponseStatus","error","undefined","response","status","isInvalidSessionError","normalizedMessage","extractErrorMessage","toLowerCase","includes","some","msg","exports","fallbackMessage","trim","length","withMessage","message","withResponse","responseMessage","data","handleAuthError","defaultMessage","code","onError","setAuthError","logger","resolvedStatus"],"sourceRoot":"../../../../../src","sources":["ui/context/utils/errorHandlers.ts"],"mappings":";;;;;;AAyBA,MAAMA,gCAAgC,GAAG,CACvC,4BAA4B,EAC5B,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,CAClB;AAED,MAAMC,QAAQ,GAAIC,KAAc,IAC9B,OAAOA,KAAK,KAAK,QAAQ,IAAIA,KAAK,KAAK,IAAI;AAE7C,MAAMC,iBAAiB,GAAIC,KAAc,IAAyB;EAChE,IAAI,CAACH,QAAQ,CAACG,KAAK,CAAC,EAAE,OAAOC,SAAS;EACtC,MAAMC,QAAQ,GAAIF,KAAK,CAAuBE,QAAQ;EACtD,OAAOA,QAAQ,EAAEC,MAAM;AACzB,CAAC;;AAED;AACA;AACA;AACA;AACO,MAAMC,qBAAqB,GAAIJ,KAAc,IAAc;EAChE,MAAMG,MAAM,GAAGJ,iBAAiB,CAACC,KAAK,CAAC;EACvC,IAAIG,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,IAAI;EACb;EAEA,IAAI,CAACN,QAAQ,CAACG,KAAK,CAAC,EAAE;IACpB,OAAO,KAAK;EACd;;EAEA;EACA,IAAKA,KAAK,CAASG,MAAM,KAAK,GAAG,EAAE;IACjC,OAAO,IAAI;EACb;EAEA,MAAME,iBAAiB,GAAGC,mBAAmB,CAACN,KAAK,CAAC,EAAEO,WAAW,CAAC,CAAC;EACnE,IAAI,CAACF,iBAAiB,EAAE;IACtB,OAAO,KAAK;EACd;;EAEA;EACA,IAAIA,iBAAiB,CAACG,QAAQ,CAAC,UAAU,CAAC,IAAIH,iBAAiB,CAACG,QAAQ,CAAC,KAAK,CAAC,EAAE;IAC/E,OAAO,IAAI;EACb;EAEA,OAAOZ,gCAAgC,CAACa,IAAI,CAAEC,GAAG,IAC/CL,iBAAiB,CAACG,QAAQ,CAACE,GAAG,CAACH,WAAW,CAAC,CAAC,CAC9C,CAAC;AACH,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AALAI,OAAA,CAAAP,qBAAA,GAAAA,qBAAA;AAMO,MAAME,mBAAmB,GAAGA,CACjCN,KAAc,EACdY,eAAe,GAAG,kBAAkB,KACzB;EACX,IAAI,OAAOZ,KAAK,KAAK,QAAQ,IAAIA,KAAK,CAACa,IAAI,CAAC,CAAC,CAACC,MAAM,GAAG,CAAC,EAAE;IACxD,OAAOd,KAAK;EACd;EAEA,IAAI,CAACH,QAAQ,CAACG,KAAK,CAAC,EAAE;IACpB,OAAOY,eAAe;EACxB;EAEA,MAAMG,WAAW,GAAGf,KAAyB;EAC7C,IAAIe,WAAW,CAACC,OAAO,IAAID,WAAW,CAACC,OAAO,CAACH,IAAI,CAAC,CAAC,CAACC,MAAM,GAAG,CAAC,EAAE;IAChE,OAAOC,WAAW,CAACC,OAAO;EAC5B;EAEA,MAAMC,YAAY,GAAGjB,KAA0B;EAC/C,MAAMkB,eAAe,GACnBD,YAAY,CAACf,QAAQ,EAAEiB,IAAI,EAAEH,OAAO,IAAIC,YAAY,CAACf,QAAQ,EAAEiB,IAAI,EAAEnB,KAAK;EAE5E,IAAI,OAAOkB,eAAe,KAAK,QAAQ,IAAIA,eAAe,CAACL,IAAI,CAAC,CAAC,CAACC,MAAM,GAAG,CAAC,EAAE;IAC5E,OAAOI,eAAe;EACxB;EAEA,OAAON,eAAe;AACxB,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AANAD,OAAA,CAAAL,mBAAA,GAAAA,mBAAA;AAOO,MAAMc,eAAe,GAAGA,CAC7BpB,KAAc,EACd;EACEqB,cAAc;EACdC,IAAI;EACJnB,MAAM;EACNoB,OAAO;EACPC,YAAY;EACZC;AACsB,CAAC,KACd;EACX,MAAMC,cAAc,GAAGvB,MAAM,IAAIJ,iBAAiB,CAACC,KAAK,CAAC,KAAKI,qBAAqB,CAACJ,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;EACvG,MAAMgB,OAAO,GAAGV,mBAAmB,CAACN,KAAK,EAAEqB,cAAc,CAAC;EAE1D,IAAII,MAAM,EAAE;IACVA,MAAM,CAACT,OAAO,EAAEhB,KAAK,CAAC;EACxB;EAEAwB,YAAY,GAAGR,OAAO,CAAC;EAEvBO,OAAO,GAAG;IACRP,OAAO;IACPM,IAAI;IACJnB,MAAM,EAAEuB;EACV,CAAC,CAAC;EAEF,OAAOV,OAAO;AAChB,CAAC;AAACL,OAAA,CAAAS,eAAA,GAAAA,eAAA","ignoreList":[]}
|