@oxyhq/services 5.11.10 → 5.11.12
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/AnimationExample.js +1 -1
- package/lib/commonjs/ui/components/AnimationExample.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +1 -1
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/Header.js +2 -2
- package/lib/commonjs/ui/components/Header.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +3 -3
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/StepBasedScreen.README.md +337 -0
- package/lib/commonjs/ui/components/StepBasedScreen.js +361 -0
- package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -0
- package/lib/commonjs/ui/components/icon/OxyIcon.js +3 -3
- package/lib/commonjs/ui/components/icon/OxyIcon.js.map +1 -1
- package/lib/commonjs/ui/components/internal/PinInput.js +1 -1
- package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
- package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +7 -7
- package/lib/commonjs/ui/context/OxyContext.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/ProfileScreen.js +55 -55
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js +87 -219
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +138 -235
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +139 -742
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +3 -3
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +2 -2
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +110 -0
- package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +138 -0
- package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +141 -0
- package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +165 -0
- package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +150 -0
- package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +171 -0
- package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +163 -0
- package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +170 -0
- package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +72 -0
- package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -0
- package/lib/module/ui/components/AnimationExample.js +1 -1
- package/lib/module/ui/components/AnimationExample.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +1 -1
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/Header.js +2 -2
- package/lib/module/ui/components/Header.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +3 -3
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/Section.js.map +1 -1
- package/lib/module/ui/components/SectionTitle.js.map +1 -1
- package/lib/module/ui/components/StepBasedScreen.README.md +337 -0
- package/lib/module/ui/components/StepBasedScreen.js +356 -0
- package/lib/module/ui/components/StepBasedScreen.js.map +1 -0
- package/lib/module/ui/components/icon/FAIRWalletIcon.js.map +1 -1
- package/lib/module/ui/components/icon/OxyIcon.js +3 -3
- package/lib/module/ui/components/icon/OxyIcon.js.map +1 -1
- package/lib/module/ui/components/internal/PinInput.js +1 -1
- package/lib/module/ui/components/internal/PinInput.js.map +1 -1
- package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +7 -7
- package/lib/module/ui/context/OxyContext.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/ProfileScreen.js +55 -55
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/RecoverAccountScreen.js +91 -222
- package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +140 -237
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +141 -743
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInPasswordStep.js +3 -3
- package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInUsernameStep.js +2 -2
- package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverRequestStep.js +105 -0
- package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -0
- package/lib/module/ui/screens/steps/RecoverSuccessStep.js +133 -0
- package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -0
- package/lib/module/ui/screens/steps/RecoverVerifyStep.js +136 -0
- package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -0
- package/lib/module/ui/screens/steps/SignInPasswordStep.js +160 -0
- package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -0
- package/lib/module/ui/screens/steps/SignInUsernameStep.js +145 -0
- package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -0
- package/lib/module/ui/screens/steps/SignUpIdentityStep.js +166 -0
- package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -0
- package/lib/module/ui/screens/steps/SignUpSecurityStep.js +158 -0
- package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -0
- package/lib/module/ui/screens/steps/SignUpSummaryStep.js +165 -0
- package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -0
- package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +67 -0
- package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -0
- package/lib/typescript/models/interfaces.d.ts +4 -3
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/ui/components/AnimationExample.d.ts +1 -1
- package/lib/typescript/ui/components/AnimationExample.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyPayButton.d.ts +2 -2
- package/lib/typescript/ui/components/OxyPayButton.d.ts.map +1 -1
- package/lib/typescript/ui/components/Section.d.ts +2 -1
- package/lib/typescript/ui/components/Section.d.ts.map +1 -1
- package/lib/typescript/ui/components/SectionTitle.d.ts +2 -1
- package/lib/typescript/ui/components/SectionTitle.d.ts.map +1 -1
- package/lib/typescript/ui/components/StepBasedScreen.d.ts +24 -0
- package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -0
- package/lib/typescript/ui/components/icon/FAIRWalletIcon.d.ts +2 -1
- package/lib/typescript/ui/components/icon/FAIRWalletIcon.d.ts.map +1 -1
- package/lib/typescript/ui/components/icon/OxyIcon.d.ts +1 -1
- package/lib/typescript/ui/components/icon/OxyIcon.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/PinInput.d.ts +9 -1
- package/lib/typescript/ui/components/internal/PinInput.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +2 -1
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts +2 -2
- package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts +2 -9
- package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignUpScreen.d.ts +1 -1
- package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts +21 -0
- package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts +18 -0
- package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts +24 -0
- package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +27 -0
- package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts +27 -0
- package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts +25 -0
- package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts +26 -0
- package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts +16 -0
- package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts +13 -0
- package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -0
- package/package.json +2 -3
- package/src/models/interfaces.ts +5 -3
- package/src/ui/components/AnimationExample.tsx +9 -8
- package/src/ui/components/FollowButton.tsx +2 -2
- package/src/ui/components/Header.tsx +2 -2
- package/src/ui/components/OxyPayButton.tsx +2 -2
- package/src/ui/components/OxyProvider.tsx +4 -4
- package/src/ui/components/Section.tsx +7 -7
- package/src/ui/components/SectionTitle.tsx +2 -2
- package/src/ui/components/StepBasedScreen.README.md +337 -0
- package/src/ui/components/StepBasedScreen.tsx +417 -0
- package/src/ui/components/icon/FAIRWalletIcon.tsx +2 -2
- package/src/ui/components/icon/OxyIcon.tsx +10 -11
- package/src/ui/components/internal/PinInput.tsx +13 -4
- package/src/ui/components/photogrid/JustifiedPhotoGrid.tsx +1 -1
- package/src/ui/context/OxyContext.tsx +12 -11
- package/src/ui/screens/PaymentGatewayScreen.tsx +3 -3
- package/src/ui/screens/ProfileScreen.tsx +54 -54
- package/src/ui/screens/RecoverAccountScreen.tsx +98 -211
- package/src/ui/screens/SignInScreen.tsx +148 -271
- package/src/ui/screens/SignUpScreen.tsx +146 -748
- package/src/ui/screens/internal/SignInPasswordStep.tsx +3 -3
- package/src/ui/screens/internal/SignInUsernameStep.tsx +2 -2
- package/src/ui/screens/steps/RecoverRequestStep.tsx +130 -0
- package/src/ui/screens/steps/RecoverSuccessStep.tsx +131 -0
- package/src/ui/screens/steps/RecoverVerifyStep.tsx +153 -0
- package/src/ui/screens/steps/SignInPasswordStep.tsx +172 -0
- package/src/ui/screens/steps/SignInUsernameStep.tsx +176 -0
- package/src/ui/screens/steps/SignUpIdentityStep.tsx +204 -0
- package/src/ui/screens/steps/SignUpSecurityStep.tsx +191 -0
- package/src/ui/screens/steps/SignUpSummaryStep.tsx +130 -0
- package/src/ui/screens/steps/SignUpWelcomeStep.tsx +65 -0
|
@@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
|
|
|
3
3
|
import { View, Text, StyleSheet, ActivityIndicator, ScrollView, TouchableOpacity, Image } from 'react-native';
|
|
4
4
|
import type { BaseScreenProps } from '../navigation/types';
|
|
5
5
|
import { useOxy } from '../context/OxyContext';
|
|
6
|
+
import { useThemeColors } from '../styles';
|
|
6
7
|
import Avatar from '../components/Avatar';
|
|
7
8
|
import { FollowButton } from '../components';
|
|
8
9
|
import { useFollow } from '../hooks/useFollow';
|
|
@@ -39,10 +40,8 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
39
40
|
setFollowingCount,
|
|
40
41
|
} = useFollow(userId);
|
|
41
42
|
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
|
|
45
|
-
const primaryColor = '#d169e5';
|
|
43
|
+
const colors = useThemeColors(theme);
|
|
44
|
+
const styles = createStyles(colors);
|
|
46
45
|
|
|
47
46
|
// Check if current user is viewing their own profile
|
|
48
47
|
const isOwnProfile = currentUser && currentUser.id === userId;
|
|
@@ -154,27 +153,27 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
154
153
|
|
|
155
154
|
if (isLoading) {
|
|
156
155
|
return (
|
|
157
|
-
<View style={[styles.container, { backgroundColor, justifyContent: 'center' }]}>
|
|
158
|
-
<ActivityIndicator size="large" color={
|
|
156
|
+
<View style={[styles.container, { backgroundColor: colors.background, justifyContent: 'center' }]}>
|
|
157
|
+
<ActivityIndicator size="large" color={colors.primary} />
|
|
159
158
|
</View>
|
|
160
159
|
);
|
|
161
160
|
}
|
|
162
161
|
|
|
163
162
|
if (error) {
|
|
164
163
|
return (
|
|
165
|
-
<View style={[styles.container, { backgroundColor }]}>
|
|
164
|
+
<View style={[styles.container, { backgroundColor: colors.background }]}>
|
|
166
165
|
<View style={styles.errorHeader}>
|
|
167
166
|
{goBack && (
|
|
168
167
|
<TouchableOpacity onPress={goBack} style={styles.backButton}>
|
|
169
|
-
<Ionicons name="arrow-back" size={24} color={
|
|
168
|
+
<Ionicons name="arrow-back" size={24} color={colors.text} />
|
|
170
169
|
</TouchableOpacity>
|
|
171
170
|
)}
|
|
172
|
-
<Text style={[styles.errorTitle, { color:
|
|
171
|
+
<Text style={[styles.errorTitle, { color: colors.text }]}>Profile Error</Text>
|
|
173
172
|
</View>
|
|
174
173
|
<View style={styles.errorContent}>
|
|
175
|
-
<Ionicons name="alert-circle" size={48} color=
|
|
176
|
-
<Text style={[styles.errorText, { color:
|
|
177
|
-
<Text style={[styles.errorSubtext, { color:
|
|
174
|
+
<Ionicons name="alert-circle" size={48} color={colors.error} style={styles.errorIcon} />
|
|
175
|
+
<Text style={[styles.errorText, { color: colors.error }]}>{error}</Text>
|
|
176
|
+
<Text style={[styles.errorSubtext, { color: colors.secondaryText }]}>
|
|
178
177
|
This could happen if the user doesn't exist or the profile service is unavailable.
|
|
179
178
|
</Text>
|
|
180
179
|
</View>
|
|
@@ -183,7 +182,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
183
182
|
}
|
|
184
183
|
|
|
185
184
|
return (
|
|
186
|
-
<View style={[styles.container, { backgroundColor }]}>
|
|
185
|
+
<View style={[styles.container, { backgroundColor: colors.background }]}>
|
|
187
186
|
<ScrollView contentContainerStyle={styles.scrollContainer}>
|
|
188
187
|
{/* Banner Image */}
|
|
189
188
|
<View style={styles.bannerContainer}>
|
|
@@ -222,55 +221,55 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
222
221
|
</View>
|
|
223
222
|
{/* Profile Info */}
|
|
224
223
|
<View style={styles.header}>
|
|
225
|
-
<Text style={[styles.displayName, { color:
|
|
224
|
+
<Text style={[styles.displayName, { color: colors.text }]}>{profile?.displayName || profile?.username || username || profile?.id}</Text>
|
|
226
225
|
{profile?.username && (
|
|
227
|
-
<Text style={[styles.subText, { color:
|
|
226
|
+
<Text style={[styles.subText, { color: colors.secondaryText }]}>@{profile.username}</Text>
|
|
228
227
|
)}
|
|
229
228
|
{/* Bio placeholder */}
|
|
230
|
-
<Text style={[styles.bio, { color:
|
|
229
|
+
<Text style={[styles.bio, { color: colors.text }]}>{profile?.bio || 'This user has no bio yet.'}</Text>
|
|
231
230
|
|
|
232
231
|
{/* Info Grid Row */}
|
|
233
232
|
<View style={styles.infoGrid}>
|
|
234
233
|
{profile?.createdAt && (
|
|
235
234
|
<View style={styles.infoGridItem}>
|
|
236
|
-
<Ionicons name="calendar-outline" size={16} color={
|
|
237
|
-
<Text style={[styles.infoGridText, { color:
|
|
235
|
+
<Ionicons name="calendar-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
236
|
+
<Text style={[styles.infoGridText, { color: colors.secondaryText }]}>Joined {new Date(profile.createdAt).toLocaleDateString()}</Text>
|
|
238
237
|
</View>
|
|
239
238
|
)}
|
|
240
239
|
{profile?.location && (
|
|
241
240
|
<View style={styles.infoGridItem}>
|
|
242
|
-
<Ionicons name="location-outline" size={16} color={
|
|
243
|
-
<Text style={[styles.infoGridText, { color:
|
|
241
|
+
<Ionicons name="location-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
242
|
+
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.location}</Text>
|
|
244
243
|
</View>
|
|
245
244
|
)}
|
|
246
245
|
{profile?.website && (
|
|
247
246
|
<View style={styles.infoGridItem}>
|
|
248
|
-
<Ionicons name="globe-outline" size={16} color={
|
|
249
|
-
<Text style={[styles.infoGridText, { color:
|
|
247
|
+
<Ionicons name="globe-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
248
|
+
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.website}</Text>
|
|
250
249
|
</View>
|
|
251
250
|
)}
|
|
252
251
|
{profile?.company && (
|
|
253
252
|
<View style={styles.infoGridItem}>
|
|
254
|
-
<Ionicons name="business-outline" size={16} color={
|
|
255
|
-
<Text style={[styles.infoGridText, { color:
|
|
253
|
+
<Ionicons name="business-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
254
|
+
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.company}</Text>
|
|
256
255
|
</View>
|
|
257
256
|
)}
|
|
258
257
|
{profile?.jobTitle && (
|
|
259
258
|
<View style={styles.infoGridItem}>
|
|
260
|
-
<Ionicons name="briefcase-outline" size={16} color={
|
|
261
|
-
<Text style={[styles.infoGridText, { color:
|
|
259
|
+
<Ionicons name="briefcase-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
260
|
+
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.jobTitle}</Text>
|
|
262
261
|
</View>
|
|
263
262
|
)}
|
|
264
263
|
{profile?.education && (
|
|
265
264
|
<View style={styles.infoGridItem}>
|
|
266
|
-
<Ionicons name="school-outline" size={16} color={
|
|
267
|
-
<Text style={[styles.infoGridText, { color:
|
|
265
|
+
<Ionicons name="school-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
266
|
+
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>{profile.education}</Text>
|
|
268
267
|
</View>
|
|
269
268
|
)}
|
|
270
269
|
{profile?.birthday && (
|
|
271
270
|
<View style={styles.infoGridItem}>
|
|
272
|
-
<Ionicons name="gift-outline" size={16} color={
|
|
273
|
-
<Text style={[styles.infoGridText, { color:
|
|
271
|
+
<Ionicons name="gift-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
272
|
+
<Text style={[styles.infoGridText, { color: colors.secondaryText }]}>Born {new Date(profile.birthday).toLocaleDateString()}</Text>
|
|
274
273
|
</View>
|
|
275
274
|
)}
|
|
276
275
|
{links.length > 0 && (
|
|
@@ -278,12 +277,12 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
278
277
|
style={styles.infoGridItem}
|
|
279
278
|
onPress={() => navigate?.('UserLinks', { userId, links })}
|
|
280
279
|
>
|
|
281
|
-
<Ionicons name="link-outline" size={16} color={
|
|
282
|
-
<Text style={[styles.infoGridText, { color:
|
|
280
|
+
<Ionicons name="link-outline" size={16} color={colors.secondaryText} style={{ marginRight: 6 }} />
|
|
281
|
+
<Text style={[styles.infoGridText, { color: colors.secondaryText }]} numberOfLines={1}>
|
|
283
282
|
{links[0].url}
|
|
284
283
|
</Text>
|
|
285
284
|
{links.length > 1 && (
|
|
286
|
-
<Text style={[styles.linksMore, { color:
|
|
285
|
+
<Text style={[styles.linksMore, { color: colors.secondaryText }]}>
|
|
287
286
|
+ {links.length - 1} more
|
|
288
287
|
</Text>
|
|
289
288
|
)}
|
|
@@ -295,24 +294,24 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
295
294
|
{/* All Stats in one row */}
|
|
296
295
|
<View style={styles.statsRow}>
|
|
297
296
|
<View style={styles.statItem}>
|
|
298
|
-
<Text style={[styles.karmaAmount, { color:
|
|
299
|
-
<Text style={[styles.karmaLabel, { color:
|
|
297
|
+
<Text style={[styles.karmaAmount, { color: colors.primary }]}>{karmaTotal !== null && karmaTotal !== undefined ? karmaTotal : '--'}</Text>
|
|
298
|
+
<Text style={[styles.karmaLabel, { color: colors.secondaryText }]}>Karma</Text>
|
|
300
299
|
</View>
|
|
301
300
|
<View style={styles.statItem}>
|
|
302
301
|
{isLoadingCounts ? (
|
|
303
|
-
<ActivityIndicator size="small" color={
|
|
302
|
+
<ActivityIndicator size="small" color={colors.text} />
|
|
304
303
|
) : (
|
|
305
|
-
<Text style={[styles.karmaAmount, { color:
|
|
304
|
+
<Text style={[styles.karmaAmount, { color: colors.text }]}>{followerCount !== null ? followerCount : '--'}</Text>
|
|
306
305
|
)}
|
|
307
|
-
<Text style={[styles.karmaLabel, { color:
|
|
306
|
+
<Text style={[styles.karmaLabel, { color: colors.secondaryText }]}>Followers</Text>
|
|
308
307
|
</View>
|
|
309
308
|
<View style={styles.statItem}>
|
|
310
309
|
{isLoadingCounts ? (
|
|
311
|
-
<ActivityIndicator size="small" color={
|
|
310
|
+
<ActivityIndicator size="small" color={colors.text} />
|
|
312
311
|
) : (
|
|
313
|
-
<Text style={[styles.karmaAmount, { color:
|
|
312
|
+
<Text style={[styles.karmaAmount, { color: colors.text }]}>{followingCount !== null ? followingCount : '--'}</Text>
|
|
314
313
|
)}
|
|
315
|
-
<Text style={[styles.karmaLabel, { color:
|
|
314
|
+
<Text style={[styles.karmaLabel, { color: colors.secondaryText }]}>Following</Text>
|
|
316
315
|
</View>
|
|
317
316
|
</View>
|
|
318
317
|
</View>
|
|
@@ -321,37 +320,37 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
321
320
|
);
|
|
322
321
|
};
|
|
323
322
|
|
|
324
|
-
const
|
|
323
|
+
const createStyles = (colors: any) => StyleSheet.create({
|
|
325
324
|
container: { flex: 1 },
|
|
326
325
|
scrollContainer: { alignItems: 'stretch', paddingBottom: 40 },
|
|
327
|
-
bannerContainer: { height: 160, backgroundColor: '
|
|
328
|
-
bannerImage: { flex: 1, backgroundColor:
|
|
326
|
+
bannerContainer: { height: 160, backgroundColor: colors.primary + '20', position: 'relative', overflow: 'hidden' },
|
|
327
|
+
bannerImage: { flex: 1, backgroundColor: colors.primary }, // Placeholder, replace with Image if available
|
|
329
328
|
avatarRow: { flexDirection: 'row', alignItems: 'flex-end', marginTop: -56, paddingHorizontal: 20, justifyContent: 'space-between', zIndex: 2 },
|
|
330
|
-
avatarWrapper: { borderWidth: 5, borderColor:
|
|
329
|
+
avatarWrapper: { borderWidth: 5, borderColor: colors.background, borderRadius: 64, overflow: 'hidden', backgroundColor: colors.background },
|
|
331
330
|
actionButtonWrapper: { flex: 1, alignItems: 'flex-end', justifyContent: 'flex-end' },
|
|
332
331
|
actionButton: {
|
|
333
|
-
backgroundColor:
|
|
332
|
+
backgroundColor: colors.background,
|
|
334
333
|
borderWidth: 1,
|
|
335
|
-
borderColor:
|
|
334
|
+
borderColor: colors.primary,
|
|
336
335
|
borderRadius: 24,
|
|
337
336
|
paddingVertical: 7,
|
|
338
337
|
paddingHorizontal: 22,
|
|
339
338
|
marginBottom: 8,
|
|
340
339
|
elevation: 2,
|
|
341
|
-
shadowColor:
|
|
340
|
+
shadowColor: colors.primary,
|
|
342
341
|
shadowOffset: { width: 0, height: 1 },
|
|
343
342
|
shadowOpacity: 0.08,
|
|
344
343
|
shadowRadius: 2
|
|
345
344
|
},
|
|
346
345
|
actionButtonText: {
|
|
347
|
-
color:
|
|
346
|
+
color: colors.primary,
|
|
348
347
|
fontWeight: 'bold',
|
|
349
348
|
fontSize: 16
|
|
350
349
|
},
|
|
351
350
|
header: { alignItems: 'flex-start', width: '100%', paddingHorizontal: 20 },
|
|
352
351
|
displayName: { fontSize: 24, fontWeight: 'bold', marginTop: 10, marginBottom: 2, letterSpacing: 0.1 },
|
|
353
|
-
subText: { fontSize: 16, marginBottom: 2, color:
|
|
354
|
-
bio: { fontSize: 16, marginTop: 10, marginBottom: 10, color:
|
|
352
|
+
subText: { fontSize: 16, marginBottom: 2, color: colors.secondaryText },
|
|
353
|
+
bio: { fontSize: 16, marginTop: 10, marginBottom: 10, color: colors.text, lineHeight: 22 },
|
|
355
354
|
infoGrid: {
|
|
356
355
|
flexDirection: 'row',
|
|
357
356
|
alignItems: 'center',
|
|
@@ -365,16 +364,17 @@ const styles = StyleSheet.create({
|
|
|
365
364
|
marginBottom: 4
|
|
366
365
|
},
|
|
367
366
|
infoGridText: {
|
|
368
|
-
fontSize: 15
|
|
367
|
+
fontSize: 15,
|
|
368
|
+
color: colors.text
|
|
369
369
|
},
|
|
370
|
-
divider: { height: 1, backgroundColor:
|
|
370
|
+
divider: { height: 1, backgroundColor: colors.border, width: '100%', marginVertical: 14 },
|
|
371
371
|
linksMore: {
|
|
372
372
|
fontSize: 15,
|
|
373
373
|
marginLeft: 4
|
|
374
374
|
},
|
|
375
375
|
statsRow: { width: '100%', flex: 1, flexDirection: 'row', alignItems: 'center', marginTop: 6, marginBottom: 2, justifyContent: 'space-between' },
|
|
376
376
|
statItem: { flex: 1, alignItems: 'center', minWidth: 50, marginBottom: 12 },
|
|
377
|
-
karmaLabel: { fontSize: 14, marginBottom: 2, textAlign: 'center', color:
|
|
377
|
+
karmaLabel: { fontSize: 14, marginBottom: 2, textAlign: 'center', color: colors.secondaryText },
|
|
378
378
|
karmaAmount: { fontSize: 24, fontWeight: 'bold', textAlign: 'center', letterSpacing: 0.2 },
|
|
379
379
|
// Error handling styles
|
|
380
380
|
errorHeader: {
|
|
@@ -1,230 +1,117 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { useState, useRef, useCallback } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import PinInput from '../components/internal/PinInput';
|
|
10
|
-
|
|
11
|
-
interface RecoverAccountScreenProps {
|
|
12
|
-
navigate: (screen: string, props?: Record<string, any>) => void;
|
|
13
|
-
goBack: () => void;
|
|
14
|
-
theme: string;
|
|
15
|
-
returnTo?: string;
|
|
16
|
-
returnStep?: number;
|
|
17
|
-
returnData?: Record<string, any>;
|
|
18
|
-
}
|
|
3
|
+
import type { BaseScreenProps } from '../navigation/types';
|
|
4
|
+
import { useThemeColors } from '../styles';
|
|
5
|
+
import StepBasedScreen, { type StepConfig } from '../components/StepBasedScreen';
|
|
6
|
+
import RecoverRequestStep from './steps/RecoverRequestStep';
|
|
7
|
+
import RecoverVerifyStep from './steps/RecoverVerifyStep';
|
|
8
|
+
import RecoverSuccessStep from './steps/RecoverSuccessStep';
|
|
19
9
|
|
|
10
|
+
// Constants
|
|
20
11
|
const PIN_LENGTH = 6;
|
|
21
12
|
|
|
22
|
-
|
|
13
|
+
// Main component
|
|
14
|
+
const RecoverAccountScreen: React.FC<BaseScreenProps> = ({
|
|
15
|
+
navigate,
|
|
16
|
+
goBack,
|
|
17
|
+
theme,
|
|
18
|
+
oxyServices,
|
|
19
|
+
}) => {
|
|
20
|
+
const colors = useThemeColors(theme);
|
|
21
|
+
|
|
22
|
+
// Form state
|
|
23
23
|
const [identifier, setIdentifier] = useState('');
|
|
24
|
+
const [verificationCode, setVerificationCode] = useState('');
|
|
24
25
|
const [isLoading, setIsLoading] = useState(false);
|
|
25
26
|
const [errorMessage, setErrorMessage] = useState('');
|
|
26
27
|
const [successMessage, setSuccessMessage] = useState('');
|
|
27
|
-
const [step, setStep] = useState<'request' | 'code' | 'done'>('request');
|
|
28
|
-
const [code, setCode] = useState('');
|
|
29
|
-
const fadeAnim = useRef(new Animated.Value(1)).current;
|
|
30
|
-
const slideAnim = useRef(new Animated.Value(0)).current;
|
|
31
|
-
const colors = useThemeColors(theme as 'light' | 'dark');
|
|
32
|
-
const styles = createAuthStyles(colors, theme);
|
|
33
|
-
const identifierRef = useRef<TextInput>(null);
|
|
34
|
-
const handleRequestWithFocus = () => {
|
|
35
|
-
if (!identifier) {
|
|
36
|
-
setTimeout(() => {
|
|
37
|
-
identifierRef.current?.focus();
|
|
38
|
-
}, 0);
|
|
39
|
-
}
|
|
40
|
-
handleRequest();
|
|
41
|
-
};
|
|
42
28
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
setErrorMessage('Please enter your email or username.');
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
setIsLoading(true);
|
|
51
|
-
setTimeout(() => {
|
|
52
|
-
setIsLoading(false);
|
|
53
|
-
setStep('code');
|
|
54
|
-
setSuccessMessage('A 6-digit code has been sent to your email or phone.');
|
|
55
|
-
}, 1200);
|
|
56
|
-
};
|
|
29
|
+
// Handle back navigation
|
|
30
|
+
const handleBack = useCallback(() => {
|
|
31
|
+
navigate('SignIn');
|
|
32
|
+
}, [navigate]);
|
|
57
33
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
34
|
+
// Step configurations
|
|
35
|
+
const steps: StepConfig[] = [
|
|
36
|
+
{
|
|
37
|
+
id: 'request',
|
|
38
|
+
component: RecoverRequestStep,
|
|
39
|
+
canProceed: () => identifier.trim().length >= 3,
|
|
40
|
+
onEnter: () => {
|
|
41
|
+
// Reset messages when entering request step
|
|
42
|
+
setErrorMessage('');
|
|
43
|
+
setSuccessMessage('');
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'verify',
|
|
48
|
+
component: RecoverVerifyStep,
|
|
49
|
+
canProceed: () => verificationCode.length === PIN_LENGTH,
|
|
50
|
+
onEnter: () => {
|
|
51
|
+
// Simulate sending verification code
|
|
52
|
+
setIsLoading(true);
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
setIsLoading(false);
|
|
55
|
+
setSuccessMessage('A 6-digit code has been sent to your email or phone.');
|
|
56
|
+
}, 1000);
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'success',
|
|
61
|
+
component: RecoverSuccessStep,
|
|
62
|
+
canProceed: () => true,
|
|
63
|
+
onEnter: () => {
|
|
70
64
|
setSuccessMessage('Your account has been verified! You can now reset your password.');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}, 1200);
|
|
75
|
-
};
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
];
|
|
76
68
|
|
|
77
|
-
//
|
|
78
|
-
const
|
|
79
|
-
|
|
69
|
+
// Handle completion
|
|
70
|
+
const handleComplete = useCallback((stepData: any[]) => {
|
|
71
|
+
// Final step completed - could navigate to password reset
|
|
72
|
+
console.log('Account recovery completed');
|
|
73
|
+
}, []);
|
|
80
74
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
75
|
+
// Step data for the reusable component
|
|
76
|
+
const stepData = [
|
|
77
|
+
// Request step
|
|
78
|
+
{
|
|
79
|
+
identifier,
|
|
80
|
+
setIdentifier,
|
|
81
|
+
errorMessage,
|
|
82
|
+
setErrorMessage,
|
|
83
|
+
isLoading,
|
|
84
|
+
setIsLoading,
|
|
85
|
+
},
|
|
86
|
+
// Verify step
|
|
87
|
+
{
|
|
88
|
+
verificationCode,
|
|
89
|
+
setVerificationCode,
|
|
90
|
+
errorMessage,
|
|
91
|
+
setErrorMessage,
|
|
92
|
+
successMessage,
|
|
93
|
+
setSuccessMessage,
|
|
94
|
+
isLoading,
|
|
95
|
+
setIsLoading,
|
|
96
|
+
},
|
|
97
|
+
// Success step
|
|
98
|
+
{
|
|
99
|
+
successMessage,
|
|
100
|
+
},
|
|
101
|
+
];
|
|
107
102
|
|
|
108
103
|
return (
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
keyboardShouldPersistTaps="handled"
|
|
121
|
-
>
|
|
122
|
-
<Animated.View style={[
|
|
123
|
-
styles.stepContainer,
|
|
124
|
-
{ opacity: fadeAnim, transform: [{ translateX: slideAnim }] }
|
|
125
|
-
]}>
|
|
126
|
-
<HighFive width={100} height={100} />
|
|
127
|
-
<View style={styles.modernHeader}>
|
|
128
|
-
<Text style={[styles.modernTitle, { color: colors.text }]}>Recover Account</Text>
|
|
129
|
-
<Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>Enter your email or username to receive a 6-digit code.</Text>
|
|
130
|
-
</View>
|
|
131
|
-
{step === 'request' && (
|
|
132
|
-
<>
|
|
133
|
-
<TextField
|
|
134
|
-
ref={identifierRef}
|
|
135
|
-
label="Email or Username"
|
|
136
|
-
leading={<Ionicons name="mail-outline" size={24} color={colors.secondaryText} />}
|
|
137
|
-
value={identifier}
|
|
138
|
-
onChangeText={setIdentifier}
|
|
139
|
-
autoCapitalize="none"
|
|
140
|
-
autoCorrect={false}
|
|
141
|
-
variant="filled"
|
|
142
|
-
error={errorMessage || undefined}
|
|
143
|
-
editable={!isLoading}
|
|
144
|
-
autoFocus
|
|
145
|
-
testID="recover-identifier-input"
|
|
146
|
-
onSubmitEditing={handleRequestWithFocus}
|
|
147
|
-
/>
|
|
148
|
-
<GroupedPillButtons
|
|
149
|
-
buttons={[
|
|
150
|
-
{
|
|
151
|
-
text: 'Back',
|
|
152
|
-
onPress: handleBack,
|
|
153
|
-
icon: 'arrow-back',
|
|
154
|
-
variant: 'transparent',
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
text: 'Send Code',
|
|
158
|
-
onPress: handleRequest,
|
|
159
|
-
icon: 'mail-open-outline',
|
|
160
|
-
variant: 'primary',
|
|
161
|
-
loading: isLoading,
|
|
162
|
-
disabled: isLoading,
|
|
163
|
-
},
|
|
164
|
-
]}
|
|
165
|
-
colors={colors}
|
|
166
|
-
/>
|
|
167
|
-
</>
|
|
168
|
-
)}
|
|
169
|
-
{step === 'code' && (
|
|
170
|
-
<>
|
|
171
|
-
<PinInput
|
|
172
|
-
value={code}
|
|
173
|
-
onChange={setCode}
|
|
174
|
-
length={PIN_LENGTH}
|
|
175
|
-
disabled={isLoading}
|
|
176
|
-
autoFocus
|
|
177
|
-
colors={colors}
|
|
178
|
-
/>
|
|
179
|
-
{successMessage && (
|
|
180
|
-
<View style={styles.belowInputMessage}>
|
|
181
|
-
<Ionicons name="checkmark-circle" size={16} color={colors.success} />
|
|
182
|
-
<Text style={[styles.belowInputText, { color: colors.success }]}>{successMessage}</Text>
|
|
183
|
-
</View>
|
|
184
|
-
)}
|
|
185
|
-
{errorMessage ? (
|
|
186
|
-
<Text style={[styles.successText, { color: colors.error, marginBottom: 12 }]}>{errorMessage}</Text>
|
|
187
|
-
) : null}
|
|
188
|
-
<GroupedPillButtons
|
|
189
|
-
buttons={[
|
|
190
|
-
{
|
|
191
|
-
text: 'Back',
|
|
192
|
-
onPress: handleBack,
|
|
193
|
-
icon: 'arrow-back',
|
|
194
|
-
variant: 'transparent',
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
text: 'Verify Code',
|
|
198
|
-
onPress: handleVerifyCode,
|
|
199
|
-
icon: 'checkmark-circle-outline',
|
|
200
|
-
variant: 'primary',
|
|
201
|
-
loading: isLoading,
|
|
202
|
-
disabled: isLoading,
|
|
203
|
-
},
|
|
204
|
-
]}
|
|
205
|
-
colors={colors}
|
|
206
|
-
/>
|
|
207
|
-
</>
|
|
208
|
-
)}
|
|
209
|
-
{step === 'done' && (
|
|
210
|
-
<>
|
|
211
|
-
<Text style={[styles.successText, { color: colors.success, marginBottom: 24 }]}>{successMessage}</Text>
|
|
212
|
-
<GroupedPillButtons
|
|
213
|
-
buttons={[
|
|
214
|
-
{
|
|
215
|
-
text: 'Back',
|
|
216
|
-
onPress: handleBack,
|
|
217
|
-
icon: 'arrow-back',
|
|
218
|
-
variant: 'primary',
|
|
219
|
-
},
|
|
220
|
-
]}
|
|
221
|
-
colors={colors}
|
|
222
|
-
/>
|
|
223
|
-
</>
|
|
224
|
-
)}
|
|
225
|
-
</Animated.View>
|
|
226
|
-
</ScrollView>
|
|
227
|
-
</KeyboardAvoidingView>
|
|
104
|
+
<StepBasedScreen
|
|
105
|
+
steps={steps}
|
|
106
|
+
stepData={stepData}
|
|
107
|
+
onComplete={handleComplete}
|
|
108
|
+
navigate={navigate}
|
|
109
|
+
goBack={handleBack}
|
|
110
|
+
theme={theme}
|
|
111
|
+
oxyServices={oxyServices}
|
|
112
|
+
showProgressIndicator={true}
|
|
113
|
+
enableAnimations={true}
|
|
114
|
+
/>
|
|
228
115
|
);
|
|
229
116
|
};
|
|
230
117
|
|