@oxyhq/services 5.11.9 → 5.11.10
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 +213 -0
- package/lib/commonjs/ui/components/AnimationExample.js.map +1 -0
- package/lib/commonjs/ui/components/FollowButton.js +58 -47
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedItem.js +2 -1
- package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedSection.js +3 -0
- package/lib/commonjs/ui/components/GroupedSection.js.map +1 -1
- package/lib/commonjs/ui/components/Header.js +25 -11
- package/lib/commonjs/ui/components/Header.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +69 -33
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileCard.js +5 -1
- package/lib/commonjs/ui/components/ProfileCard.js.map +1 -1
- package/lib/commonjs/ui/components/index.js +0 -7
- package/lib/commonjs/ui/components/index.js.map +1 -1
- package/lib/commonjs/ui/components/internal/TextField.js +8 -4
- package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
- package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js +161 -0
- package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -0
- package/lib/commonjs/ui/context/OxyContext.js +97 -38
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useFollow.types.js +2 -0
- package/lib/commonjs/ui/hooks/useFollow.types.js.map +1 -0
- package/lib/commonjs/ui/navigation/OxyRouter.js +10 -0
- package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +26 -14
- package/lib/commonjs/ui/screens/AccountCenterScreen.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/AccountSettingsScreen.js +64 -15
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +4 -4
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +72 -75
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +286 -126
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +322 -0
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/ProfileScreen.js +1 -1
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js +176 -174
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +43 -52
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +6 -4
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +386 -0
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +25 -15
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +16 -9
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/styles/authStyles.js +1 -1
- package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
- package/lib/module/ui/components/AnimationExample.js +209 -0
- package/lib/module/ui/components/AnimationExample.js.map +1 -0
- package/lib/module/ui/components/FollowButton.js +58 -47
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/GroupedItem.js +2 -1
- package/lib/module/ui/components/GroupedItem.js.map +1 -1
- package/lib/module/ui/components/GroupedSection.js +3 -0
- package/lib/module/ui/components/GroupedSection.js.map +1 -1
- package/lib/module/ui/components/Header.js +25 -11
- package/lib/module/ui/components/Header.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +70 -34
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/ProfileCard.js +5 -1
- package/lib/module/ui/components/ProfileCard.js.map +1 -1
- package/lib/module/ui/components/index.js +0 -1
- package/lib/module/ui/components/index.js.map +1 -1
- package/lib/module/ui/components/internal/TextField.js +8 -4
- package/lib/module/ui/components/internal/TextField.js.map +1 -1
- package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js +156 -0
- package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -0
- package/lib/module/ui/context/OxyContext.js +97 -39
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useFollow.types.js +2 -0
- package/lib/module/ui/hooks/useFollow.types.js.map +1 -0
- package/lib/module/ui/navigation/OxyRouter.js +10 -0
- package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +12 -1
- package/lib/module/ui/screens/AccountCenterScreen.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/AccountSettingsScreen.js +64 -15
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +4 -4
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +72 -75
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +285 -125
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +319 -0
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -0
- package/lib/module/ui/screens/ProfileScreen.js +1 -1
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js +177 -175
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +44 -53
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +6 -4
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js +382 -0
- package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -0
- package/lib/module/ui/screens/internal/SignInPasswordStep.js +23 -14
- package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInUsernameStep.js +15 -9
- package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/module/ui/styles/authStyles.js +1 -1
- package/lib/module/ui/styles/authStyles.js.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +1 -5
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/models/session.d.ts +1 -4
- package/lib/typescript/models/session.d.ts.map +1 -1
- package/lib/typescript/ui/components/AnimationExample.d.ts +4 -0
- package/lib/typescript/ui/components/AnimationExample.d.ts.map +1 -0
- 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/Header.d.ts +9 -0
- package/lib/typescript/ui/components/Header.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/ProfileCard.d.ts +1 -3
- package/lib/typescript/ui/components/ProfileCard.d.ts.map +1 -1
- package/lib/typescript/ui/components/index.d.ts +0 -1
- package/lib/typescript/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
- package/lib/typescript/ui/components/photogrid/JustifiedPhotoGrid.d.ts +27 -0
- package/lib/typescript/ui/components/photogrid/JustifiedPhotoGrid.d.ts.map +1 -0
- package/lib/typescript/ui/context/OxyContext.d.ts +6 -2
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useFollow.types.d.ts +33 -0
- package/lib/typescript/ui/hooks/useFollow.types.d.ts.map +1 -0
- package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/types.d.ts +5 -0
- package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts +18 -1
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts +7 -0
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -0
- package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts +13 -0
- package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -0
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +5 -5
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts +4 -4
- package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
- package/lib/typescript/ui/styles/authStyles.d.ts +1 -1
- package/package.json +10 -2
- package/src/models/interfaces.ts +2 -5
- package/src/models/session.ts +1 -4
- package/src/ui/components/AnimationExample.tsx +194 -0
- package/src/ui/components/FollowButton.tsx +65 -45
- package/src/ui/components/GroupedItem.tsx +1 -0
- package/src/ui/components/GroupedSection.tsx +1 -1
- package/src/ui/components/Header.tsx +36 -12
- package/src/ui/components/OxyProvider.tsx +66 -32
- package/src/ui/components/ProfileCard.tsx +6 -8
- package/src/ui/components/index.ts +0 -1
- package/src/ui/components/internal/TextField.tsx +12 -6
- package/src/ui/components/photogrid/JustifiedPhotoGrid.tsx +158 -0
- package/src/ui/context/OxyContext.tsx +84 -54
- package/src/ui/hooks/useFollow.types.ts +33 -0
- package/src/ui/navigation/OxyRouter.tsx +10 -0
- package/src/ui/navigation/types.ts +6 -0
- package/src/ui/screens/AccountCenterScreen.tsx +13 -7
- package/src/ui/screens/AccountOverviewScreen.tsx +3 -3
- package/src/ui/screens/AccountSettingsScreen.tsx +65 -13
- package/src/ui/screens/AccountSwitcherScreen.tsx +4 -4
- package/src/ui/screens/FeedbackScreen.tsx +57 -80
- package/src/ui/screens/FileManagementScreen.tsx +278 -175
- package/src/ui/screens/LanguageSelectorScreen.tsx +322 -0
- package/src/ui/screens/ProfileScreen.tsx +6 -1
- package/src/ui/screens/SessionManagementScreen.tsx +148 -151
- package/src/ui/screens/SignInScreen.tsx +43 -62
- package/src/ui/screens/SignUpScreen.tsx +3 -5
- package/src/ui/screens/WelcomeNewUserScreen.tsx +272 -0
- package/src/ui/screens/internal/SignInPasswordStep.tsx +28 -13
- package/src/ui/screens/internal/SignInUsernameStep.tsx +21 -11
- package/src/ui/screens/karma/KarmaCenterScreen.tsx +1 -1
- package/src/ui/styles/authStyles.ts +1 -1
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { View, Text, TouchableOpacity, StyleSheet, Platform, Animated, ScrollView } from 'react-native';
|
|
3
|
+
import type { BaseScreenProps } from '../navigation/types';
|
|
4
|
+
import { useOxy } from '../context/OxyContext';
|
|
5
|
+
import Avatar from '../components/Avatar';
|
|
6
|
+
import { Ionicons } from '@expo/vector-icons';
|
|
7
|
+
import { toast } from '../../lib/sonner';
|
|
8
|
+
import { useAuthStore } from '../stores/authStore';
|
|
9
|
+
import { useThemeColors } from '../styles';
|
|
10
|
+
import GroupedPillButtons from '../components/internal/GroupedPillButtons';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Post-signup welcome & onboarding screen.
|
|
14
|
+
* - Greets the newly registered user
|
|
15
|
+
* - Lets them immediately set / change their avatar using existing FileManagement picker
|
|
16
|
+
* - Only when the user presses "Continue" do we invoke onAuthenticated to finish flow & close sheet
|
|
17
|
+
*/
|
|
18
|
+
const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
19
|
+
navigate,
|
|
20
|
+
onAuthenticated,
|
|
21
|
+
theme,
|
|
22
|
+
newUser,
|
|
23
|
+
}) => {
|
|
24
|
+
const { user, oxyServices } = useOxy();
|
|
25
|
+
const updateUser = useAuthStore(s => s.updateUser);
|
|
26
|
+
const currentUser = user || newUser; // fallback
|
|
27
|
+
const colors = useThemeColors(theme);
|
|
28
|
+
const styles = useMemo(() => createStyles(theme), [theme]);
|
|
29
|
+
|
|
30
|
+
// Animation state
|
|
31
|
+
const fadeAnim = useRef(new Animated.Value(1)).current;
|
|
32
|
+
const slideAnim = useRef(new Animated.Value(0)).current;
|
|
33
|
+
const [currentStep, setCurrentStep] = useState(0);
|
|
34
|
+
|
|
35
|
+
const avatarUri = currentUser?.avatar ? oxyServices.getFileDownloadUrl(currentUser.avatar as string, 'thumb') : undefined;
|
|
36
|
+
|
|
37
|
+
// Steps content
|
|
38
|
+
const steps: Array<{ key: string; title: string; bullets?: string[]; body?: string; showAvatar?: boolean; }> = [
|
|
39
|
+
{ key: 'welcome', title: `Welcome${currentUser?.username ? `, ${currentUser.username}` : ''} 👋`, body: 'You just created an account in a calm, ethical space. A few quick things — then you\'re in.' },
|
|
40
|
+
{ key: 'account', title: 'One Account. Simple.', bullets: ['One identity across everything', 'No re‑signing in all the time', 'Your preferences stay with you'] },
|
|
41
|
+
{ key: 'principles', title: 'What We Stand For', bullets: ['Privacy by default', 'No manipulative feeds', 'You decide what to share', 'No selling your data'] },
|
|
42
|
+
{ key: 'karma', title: 'Karma = Trust & Growth', body: 'Oxy Karma is a points system that reacts to what you do. Helpful, respectful, constructive actions earn it. Harmful or low‑effort stuff chips it away. More karma can unlock benefits; low karma can limit features. It keeps things fair and rewards real contribution.' },
|
|
43
|
+
{ key: 'avatar', title: 'Make It Yours', body: 'Add an avatar so people recognize you. It will show anywhere you show up here. Skip if you want — you can add it later.', showAvatar: true },
|
|
44
|
+
{ key: 'ready', title: 'You\'re Ready', body: 'Explore. Contribute. Earn karma. Stay in control.' }
|
|
45
|
+
];
|
|
46
|
+
const totalSteps = steps.length;
|
|
47
|
+
const avatarStepIndex = steps.findIndex(s => s.showAvatar);
|
|
48
|
+
|
|
49
|
+
const animateToStep = (next: number) => {
|
|
50
|
+
Animated.timing(fadeAnim, { toValue: 0, duration: 180, useNativeDriver: Platform.OS !== 'web' }).start(() => {
|
|
51
|
+
setCurrentStep(next);
|
|
52
|
+
slideAnim.setValue(-40);
|
|
53
|
+
Animated.parallel([
|
|
54
|
+
Animated.timing(fadeAnim, { toValue: 1, duration: 220, useNativeDriver: Platform.OS !== 'web' }),
|
|
55
|
+
Animated.spring(slideAnim, { toValue: 0, useNativeDriver: Platform.OS !== 'web', friction: 9 })
|
|
56
|
+
]).start();
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const nextStep = useCallback(() => { if (currentStep < totalSteps - 1) animateToStep(currentStep + 1); }, [currentStep, totalSteps]);
|
|
61
|
+
const prevStep = useCallback(() => { if (currentStep > 0) animateToStep(currentStep - 1); }, [currentStep]);
|
|
62
|
+
const skipToAvatar = useCallback(() => { if (avatarStepIndex >= 0) animateToStep(avatarStepIndex); }, [avatarStepIndex]);
|
|
63
|
+
const finish = useCallback(() => { if (onAuthenticated && currentUser) onAuthenticated(currentUser); }, [onAuthenticated, currentUser]);
|
|
64
|
+
const openAvatarPicker = useCallback(() => {
|
|
65
|
+
navigate('FileManagement', {
|
|
66
|
+
selectMode: true,
|
|
67
|
+
multiSelect: false,
|
|
68
|
+
disabledMimeTypes: ['video/', 'audio/', 'application/pdf'],
|
|
69
|
+
afterSelect: 'back',
|
|
70
|
+
onSelect: async (file: any) => {
|
|
71
|
+
if (!file.contentType.startsWith('image/')) { toast.error('Please select an image file'); return; }
|
|
72
|
+
try { await updateUser({ avatar: file.id }, oxyServices); toast.success('Avatar updated'); } catch (e: any) { toast.error(e.message || 'Failed to update avatar'); }
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}, [navigate, updateUser, oxyServices]);
|
|
76
|
+
|
|
77
|
+
const step = steps[currentStep];
|
|
78
|
+
const pillButtons = useMemo(() => {
|
|
79
|
+
if (currentStep === totalSteps - 1) {
|
|
80
|
+
return [
|
|
81
|
+
{ text: 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
82
|
+
{ text: 'Enter', onPress: finish, icon: 'log-in-outline', variant: 'primary' },
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
if (currentStep === 0) {
|
|
86
|
+
const arr: any[] = [];
|
|
87
|
+
if (avatarStepIndex > 0) arr.push({ text: 'Skip', onPress: skipToAvatar, icon: 'play-skip-forward', variant: 'transparent' });
|
|
88
|
+
arr.push({ text: 'Next', onPress: nextStep, icon: 'arrow-forward', variant: 'primary' });
|
|
89
|
+
return arr;
|
|
90
|
+
}
|
|
91
|
+
if (step.showAvatar) {
|
|
92
|
+
return [
|
|
93
|
+
{ text: 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
94
|
+
{ text: avatarUri ? 'Continue' : 'Skip', onPress: nextStep, icon: 'arrow-forward', variant: 'primary' },
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
return [
|
|
98
|
+
{ text: 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
99
|
+
{ text: 'Next', onPress: nextStep, icon: 'arrow-forward', variant: 'primary' },
|
|
100
|
+
];
|
|
101
|
+
}, [currentStep, totalSteps, prevStep, nextStep, finish, skipToAvatar, avatarStepIndex, step.showAvatar, avatarUri]);
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<View style={styles.container}>
|
|
105
|
+
<View style={styles.progressContainer}>
|
|
106
|
+
{steps.map((s, i) => (
|
|
107
|
+
<View key={s.key} style={[styles.progressDot, i === currentStep ? { backgroundColor: colors.primary, width: 22 } : { backgroundColor: colors.border }]} />
|
|
108
|
+
))}
|
|
109
|
+
</View>
|
|
110
|
+
<Animated.View style={{ opacity: fadeAnim, transform: [{ translateX: slideAnim }] }}>
|
|
111
|
+
<ScrollView contentContainerStyle={styles.scrollInner} showsVerticalScrollIndicator={false}>
|
|
112
|
+
<Text style={styles.title}>{step.title}</Text>
|
|
113
|
+
{step.body && <Text style={styles.body}>{step.body}</Text>}
|
|
114
|
+
{Array.isArray(step.bullets) && step.bullets.length > 0 && (
|
|
115
|
+
<View style={styles.bulletContainer}>
|
|
116
|
+
{step.bullets.map(b => (
|
|
117
|
+
<View key={b} style={styles.bulletRow}>
|
|
118
|
+
<Ionicons name="ellipse" size={8} color={colors.primary} style={{ marginTop: 6 }} />
|
|
119
|
+
<Text style={styles.bulletText}>{b}</Text>
|
|
120
|
+
</View>
|
|
121
|
+
))}
|
|
122
|
+
</View>
|
|
123
|
+
)}
|
|
124
|
+
{step.showAvatar && (
|
|
125
|
+
<View style={styles.avatarSection}>
|
|
126
|
+
<Avatar size={120} name={currentUser?.username} uri={avatarUri} theme={theme} style={styles.avatar} />
|
|
127
|
+
<TouchableOpacity style={styles.changeAvatarButton} onPress={openAvatarPicker}>
|
|
128
|
+
<Ionicons name="image-outline" size={18} color="#FFFFFF" />
|
|
129
|
+
<Text style={styles.changeAvatarText}>{avatarUri ? 'Change Avatar' : 'Add Avatar'}</Text>
|
|
130
|
+
</TouchableOpacity>
|
|
131
|
+
</View>
|
|
132
|
+
)}
|
|
133
|
+
<GroupedPillButtons buttons={pillButtons} colors={colors} />
|
|
134
|
+
</ScrollView>
|
|
135
|
+
</Animated.View>
|
|
136
|
+
</View>
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const createStyles = (theme: string) => {
|
|
142
|
+
const isDark = theme === 'dark';
|
|
143
|
+
const textColor = isDark ? '#FFFFFF' : '#000000';
|
|
144
|
+
const secondary = isDark ? '#CCCCCC' : '#555555';
|
|
145
|
+
const cardBg = isDark ? '#1E1E1E' : '#FFFFFF';
|
|
146
|
+
const border = isDark ? '#333333' : '#E0E0E0';
|
|
147
|
+
const primary = '#007AFF';
|
|
148
|
+
return StyleSheet.create({
|
|
149
|
+
container: {
|
|
150
|
+
width: '100%',
|
|
151
|
+
paddingHorizontal: 20,
|
|
152
|
+
},
|
|
153
|
+
scrollInner: {
|
|
154
|
+
paddingBottom: 12,
|
|
155
|
+
},
|
|
156
|
+
title: {
|
|
157
|
+
fontSize: 42,
|
|
158
|
+
fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
|
|
159
|
+
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
160
|
+
letterSpacing: -1,
|
|
161
|
+
color: textColor,
|
|
162
|
+
marginBottom: 12,
|
|
163
|
+
},
|
|
164
|
+
body: {
|
|
165
|
+
fontSize: 16,
|
|
166
|
+
lineHeight: 22,
|
|
167
|
+
color: secondary,
|
|
168
|
+
marginBottom: 28,
|
|
169
|
+
maxWidth: 620,
|
|
170
|
+
},
|
|
171
|
+
bulletContainer: {
|
|
172
|
+
gap: 10,
|
|
173
|
+
marginBottom: 32,
|
|
174
|
+
},
|
|
175
|
+
bulletRow: {
|
|
176
|
+
flexDirection: 'row',
|
|
177
|
+
alignItems: 'flex-start',
|
|
178
|
+
gap: 10,
|
|
179
|
+
},
|
|
180
|
+
bulletText: {
|
|
181
|
+
flex: 1,
|
|
182
|
+
fontSize: 15,
|
|
183
|
+
lineHeight: 20,
|
|
184
|
+
color: secondary,
|
|
185
|
+
},
|
|
186
|
+
avatarSection: {
|
|
187
|
+
width: '100%',
|
|
188
|
+
alignItems: 'center',
|
|
189
|
+
marginBottom: 40,
|
|
190
|
+
},
|
|
191
|
+
avatar: {
|
|
192
|
+
marginBottom: 16,
|
|
193
|
+
borderWidth: 4,
|
|
194
|
+
borderColor: primary + '40',
|
|
195
|
+
},
|
|
196
|
+
changeAvatarButton: {
|
|
197
|
+
flexDirection: 'row',
|
|
198
|
+
alignItems: 'center',
|
|
199
|
+
backgroundColor: primary,
|
|
200
|
+
paddingHorizontal: 18,
|
|
201
|
+
paddingVertical: 10,
|
|
202
|
+
borderRadius: 35,
|
|
203
|
+
gap: 8,
|
|
204
|
+
},
|
|
205
|
+
changeAvatarText: {
|
|
206
|
+
color: '#FFFFFF',
|
|
207
|
+
fontSize: 15,
|
|
208
|
+
fontWeight: '600',
|
|
209
|
+
},
|
|
210
|
+
progressContainer: {
|
|
211
|
+
flexDirection: 'row',
|
|
212
|
+
width: '100%',
|
|
213
|
+
justifyContent: 'center',
|
|
214
|
+
marginBottom: 24,
|
|
215
|
+
marginTop: 4,
|
|
216
|
+
},
|
|
217
|
+
progressDot: {
|
|
218
|
+
height: 10,
|
|
219
|
+
width: 10,
|
|
220
|
+
borderRadius: 5,
|
|
221
|
+
marginHorizontal: 6,
|
|
222
|
+
backgroundColor: border,
|
|
223
|
+
},
|
|
224
|
+
navBar: {
|
|
225
|
+
flexDirection: 'row',
|
|
226
|
+
alignItems: 'center',
|
|
227
|
+
width: '100%',
|
|
228
|
+
gap: 12,
|
|
229
|
+
marginTop: 8,
|
|
230
|
+
},
|
|
231
|
+
navButton: {
|
|
232
|
+
flexDirection: 'row',
|
|
233
|
+
alignItems: 'center',
|
|
234
|
+
gap: 6,
|
|
235
|
+
paddingHorizontal: 14,
|
|
236
|
+
paddingVertical: 10,
|
|
237
|
+
borderRadius: 12,
|
|
238
|
+
},
|
|
239
|
+
backButton: {
|
|
240
|
+
backgroundColor: cardBg,
|
|
241
|
+
borderWidth: 1,
|
|
242
|
+
borderColor: border,
|
|
243
|
+
},
|
|
244
|
+
skipButton: {
|
|
245
|
+
marginLeft: 'auto',
|
|
246
|
+
backgroundColor: 'transparent',
|
|
247
|
+
paddingHorizontal: 4,
|
|
248
|
+
},
|
|
249
|
+
navText: {
|
|
250
|
+
fontSize: 14,
|
|
251
|
+
fontWeight: '500',
|
|
252
|
+
},
|
|
253
|
+
primaryButton: {
|
|
254
|
+
flexDirection: 'row',
|
|
255
|
+
alignItems: 'center',
|
|
256
|
+
justifyContent: 'center',
|
|
257
|
+
gap: 8,
|
|
258
|
+
backgroundColor: primary,
|
|
259
|
+
paddingVertical: 18,
|
|
260
|
+
borderRadius: 16,
|
|
261
|
+
width: '100%',
|
|
262
|
+
},
|
|
263
|
+
primaryButtonText: {
|
|
264
|
+
color: '#FFFFFF',
|
|
265
|
+
fontSize: 16,
|
|
266
|
+
fontWeight: '600',
|
|
267
|
+
letterSpacing: 0.5,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
export default WelcomeNewUserScreen;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { useRef, useCallback, useEffect } from 'react';
|
|
3
|
-
import { View, Text,
|
|
3
|
+
import { View, Text, TouchableOpacity, type TextInput, StatusBar } from 'react-native';
|
|
4
|
+
import Animated, {
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
SharedValue,
|
|
7
|
+
} from 'react-native-reanimated';
|
|
4
8
|
import { Ionicons } from '@expo/vector-icons';
|
|
5
9
|
import Avatar from '../../components/Avatar';
|
|
6
10
|
import GroupedPillButtons from '../../components/internal/GroupedPillButtons';
|
|
@@ -8,14 +12,14 @@ import TextField from '../../components/internal/TextField';
|
|
|
8
12
|
|
|
9
13
|
interface SignInPasswordStepProps {
|
|
10
14
|
styles: any;
|
|
11
|
-
fadeAnim:
|
|
12
|
-
slideAnim:
|
|
13
|
-
scaleAnim:
|
|
15
|
+
fadeAnim: SharedValue<number>;
|
|
16
|
+
slideAnim: SharedValue<number>;
|
|
17
|
+
scaleAnim: SharedValue<number>;
|
|
14
18
|
colors: any;
|
|
15
19
|
userProfile: any;
|
|
16
20
|
username: string;
|
|
17
21
|
theme: string;
|
|
18
|
-
logoAnim:
|
|
22
|
+
logoAnim: SharedValue<number>;
|
|
19
23
|
errorMessage: string;
|
|
20
24
|
isInputFocused: boolean;
|
|
21
25
|
password: string;
|
|
@@ -53,6 +57,23 @@ const SignInPasswordStep: React.FC<SignInPasswordStepProps> = ({
|
|
|
53
57
|
}) => {
|
|
54
58
|
const inputRef = useRef<TextInput>(null);
|
|
55
59
|
|
|
60
|
+
// Animated styles
|
|
61
|
+
const containerAnimatedStyle = useAnimatedStyle(() => {
|
|
62
|
+
return {
|
|
63
|
+
opacity: fadeAnim.value,
|
|
64
|
+
transform: [
|
|
65
|
+
{ translateX: slideAnim.value },
|
|
66
|
+
{ scale: scaleAnim.value }
|
|
67
|
+
]
|
|
68
|
+
};
|
|
69
|
+
}, [fadeAnim, slideAnim, scaleAnim]);
|
|
70
|
+
|
|
71
|
+
const logoAnimatedStyle = useAnimatedStyle(() => {
|
|
72
|
+
return {
|
|
73
|
+
transform: [{ scale: logoAnim.value }]
|
|
74
|
+
};
|
|
75
|
+
}, [logoAnim]);
|
|
76
|
+
|
|
56
77
|
// Focus password input on error or when step becomes active
|
|
57
78
|
useEffect(() => {
|
|
58
79
|
if (errorMessage) {
|
|
@@ -74,18 +95,12 @@ const SignInPasswordStep: React.FC<SignInPasswordStepProps> = ({
|
|
|
74
95
|
return (
|
|
75
96
|
<Animated.View style={[
|
|
76
97
|
styles.stepContainer,
|
|
77
|
-
|
|
78
|
-
opacity: fadeAnim,
|
|
79
|
-
transform: [
|
|
80
|
-
{ translateX: slideAnim },
|
|
81
|
-
{ scale: scaleAnim }
|
|
82
|
-
]
|
|
83
|
-
}
|
|
98
|
+
containerAnimatedStyle
|
|
84
99
|
]}>
|
|
85
100
|
<View style={styles.modernUserProfileContainer}>
|
|
86
101
|
<Animated.View style={[
|
|
87
102
|
styles.avatarContainer,
|
|
88
|
-
|
|
103
|
+
logoAnimatedStyle
|
|
89
104
|
]}>
|
|
90
105
|
<Avatar
|
|
91
106
|
name={userProfile?.displayName || userProfile?.name || username}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { useRef } from 'react';
|
|
3
|
-
import { type TextInput, View, Text
|
|
3
|
+
import { type TextInput, View, Text } from 'react-native';
|
|
4
|
+
import Animated, {
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
SharedValue,
|
|
7
|
+
} from 'react-native-reanimated';
|
|
4
8
|
import { Ionicons } from '@expo/vector-icons';
|
|
5
9
|
import HighFive from '../../../assets/illustrations/HighFive';
|
|
6
10
|
import GroupedPillButtons from '../../components/internal/GroupedPillButtons';
|
|
@@ -8,9 +12,9 @@ import TextField from '../../components/internal/TextField';
|
|
|
8
12
|
|
|
9
13
|
interface SignInUsernameStepProps {
|
|
10
14
|
styles: any;
|
|
11
|
-
fadeAnim:
|
|
12
|
-
slideAnim:
|
|
13
|
-
scaleAnim:
|
|
15
|
+
fadeAnim: SharedValue<number>;
|
|
16
|
+
slideAnim: SharedValue<number>;
|
|
17
|
+
scaleAnim: SharedValue<number>;
|
|
14
18
|
colors: any;
|
|
15
19
|
isAddAccountMode: boolean;
|
|
16
20
|
user: any;
|
|
@@ -48,6 +52,18 @@ const SignInUsernameStep: React.FC<SignInUsernameStepProps> = ({
|
|
|
48
52
|
navigate,
|
|
49
53
|
}) => {
|
|
50
54
|
const inputRef = useRef<TextInput>(null);
|
|
55
|
+
|
|
56
|
+
// Animated styles
|
|
57
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
58
|
+
return {
|
|
59
|
+
opacity: fadeAnim.value,
|
|
60
|
+
transform: [
|
|
61
|
+
{ translateX: slideAnim.value },
|
|
62
|
+
{ scale: scaleAnim.value }
|
|
63
|
+
]
|
|
64
|
+
};
|
|
65
|
+
}, [fadeAnim, slideAnim, scaleAnim]);
|
|
66
|
+
|
|
51
67
|
const handleUsernameContinue = () => {
|
|
52
68
|
if (!username || validationStatus === 'invalid') {
|
|
53
69
|
setTimeout(() => {
|
|
@@ -59,13 +75,7 @@ const SignInUsernameStep: React.FC<SignInUsernameStepProps> = ({
|
|
|
59
75
|
return (
|
|
60
76
|
<Animated.View style={[
|
|
61
77
|
styles.stepContainer,
|
|
62
|
-
|
|
63
|
-
opacity: fadeAnim,
|
|
64
|
-
transform: [
|
|
65
|
-
{ translateX: slideAnim },
|
|
66
|
-
{ scale: scaleAnim }
|
|
67
|
-
]
|
|
68
|
-
}
|
|
78
|
+
animatedStyle
|
|
69
79
|
]}>
|
|
70
80
|
<HighFive width={100} height={100} />
|
|
71
81
|
<View style={styles.modernHeader}>
|
|
@@ -73,7 +73,7 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
73
73
|
<ScrollView style={styles.scrollView} contentContainerStyle={styles.scrollContainer}>
|
|
74
74
|
<View style={styles.walletHeader}>
|
|
75
75
|
<Avatar
|
|
76
|
-
uri={user?.avatar
|
|
76
|
+
uri={user?.avatar ? oxyServices.getFileDownloadUrl(user.avatar as string, 'thumb') : undefined}
|
|
77
77
|
name={user?.username}
|
|
78
78
|
size={60}
|
|
79
79
|
theme={theme}
|
|
@@ -260,7 +260,7 @@ export const createAuthStyles = (colors: AuthThemeColors, theme: string) => Styl
|
|
|
260
260
|
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
261
261
|
fontSize: 42,
|
|
262
262
|
marginBottom: 4,
|
|
263
|
-
textAlign: '
|
|
263
|
+
textAlign: 'left',
|
|
264
264
|
letterSpacing: -0.5,
|
|
265
265
|
},
|
|
266
266
|
modernUsernameSubtext: {
|