@coinbase/create-cdp-app 0.0.28 → 0.0.29
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/package.json +1 -1
- package/template-nextjs/src/app/globals.css +4 -0
- package/template-nextjs/src/components/FundWallet.tsx +2 -2
- package/template-nextjs/src/components/theme.ts +2 -2
- package/template-react/src/index.css +4 -0
- package/template-react/src/theme.ts +2 -2
- package/template-react-native/App.tsx +201 -238
- package/template-react-native/EOATransaction.tsx +222 -263
- package/template-react-native/SmartAccountTransaction.tsx +346 -202
- package/template-react-native/components/DarkModeToggle.tsx +49 -0
- package/template-react-native/components/SignInModal.tsx +342 -0
- package/template-react-native/components/SunMoonIcon.tsx +105 -0
- package/template-react-native/components/UserIcon.tsx +54 -0
- package/template-react-native/components/WalletHeader.tsx +102 -0
- package/template-react-native/components/WelcomeScreen.tsx +73 -0
- package/template-react-native/theme/ThemeContext.tsx +58 -0
- package/template-react-native/types.ts +48 -0
package/package.json
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
--cdp-example-accent-hover-color: #016969;
|
|
10
10
|
--cdp-example-accent-foreground-color: #ffffff;
|
|
11
11
|
--cdp-example-bg-low-contrast-color: #eeeeee;
|
|
12
|
+
--cdp-example-cdp-page-bg-color: #ffffff;
|
|
13
|
+
--cdp-example-cdp-page-bg-alt-color: #eef0f3;
|
|
12
14
|
--cdp-example-card-bg-color: #ffffff;
|
|
13
15
|
--cdp-example-card-border-color: #dcdcdc;
|
|
14
16
|
--cdp-example-card-max-width: 30rem;
|
|
@@ -40,6 +42,8 @@
|
|
|
40
42
|
--cdp-example-accent-hover-color: #04c0c0;
|
|
41
43
|
--cdp-example-accent-foreground-color: #0a0b0d;
|
|
42
44
|
--cdp-example-bg-low-contrast-color: #32353d;
|
|
45
|
+
--cdp-example-cdp-page-bg-color: #0a0b0d;
|
|
46
|
+
--cdp-example-cdp-page-bg-alt-color: #333333;
|
|
43
47
|
--cdp-example-card-bg-color: #141519;
|
|
44
48
|
--cdp-example-card-border-color: #24262a;
|
|
45
49
|
}
|
|
@@ -27,8 +27,8 @@ export default function FundWallet({ onSuccess }: { onSuccess: () => void }) {
|
|
|
27
27
|
<FundModal
|
|
28
28
|
country="US"
|
|
29
29
|
subdivision="CA"
|
|
30
|
-
cryptoCurrency="
|
|
31
|
-
fiatCurrency="
|
|
30
|
+
cryptoCurrency="eth"
|
|
31
|
+
fiatCurrency="usd"
|
|
32
32
|
fetchBuyQuote={fetchBuyQuote}
|
|
33
33
|
fetchBuyOptions={fetchBuyOptions}
|
|
34
34
|
network="base"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type Theme } from "@coinbase/cdp-react/theme";
|
|
2
2
|
|
|
3
3
|
export const theme: Partial<Theme> = {
|
|
4
|
-
"colors-bg-alternate": "var(--cdp-example-page-bg-alt-color)",
|
|
5
|
-
"colors-bg-default": "var(--cdp-example-
|
|
4
|
+
"colors-bg-alternate": "var(--cdp-example-cdp-page-bg-alt-color)",
|
|
5
|
+
"colors-bg-default": "var(--cdp-example-cdp-page-bg-color)",
|
|
6
6
|
"colors-bg-overlay": "var(--cdp-example-bg-overlay-color)",
|
|
7
7
|
"colors-bg-skeleton": "var(--cdp-example-bg-skeleton-color)",
|
|
8
8
|
"colors-bg-primary": "var(--cdp-example-accent-color)",
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
--cdp-example-accent-hover-color: #016969;
|
|
10
10
|
--cdp-example-accent-foreground-color: #ffffff;
|
|
11
11
|
--cdp-example-bg-low-contrast-color: #eeeeee;
|
|
12
|
+
--cdp-example-cdp-page-bg-color: #ffffff;
|
|
13
|
+
--cdp-example-cdp-page-bg-alt-color: #eef0f3;
|
|
12
14
|
--cdp-example-card-bg-color: #ffffff;
|
|
13
15
|
--cdp-example-card-border-color: #dcdcdc;
|
|
14
16
|
--cdp-example-card-max-width: 30rem;
|
|
@@ -40,6 +42,8 @@
|
|
|
40
42
|
--cdp-example-accent-hover-color: #04c0c0;
|
|
41
43
|
--cdp-example-accent-foreground-color: #0a0b0d;
|
|
42
44
|
--cdp-example-bg-low-contrast-color: #32353d;
|
|
45
|
+
--cdp-example-cdp-page-bg-color: #0a0b0d;
|
|
46
|
+
--cdp-example-cdp-page-bg-alt-color: #333333;
|
|
43
47
|
--cdp-example-card-bg-color: #141519;
|
|
44
48
|
--cdp-example-card-border-color: #24262a;
|
|
45
49
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type Theme } from "@coinbase/cdp-react/theme";
|
|
2
2
|
|
|
3
3
|
export const theme: Partial<Theme> = {
|
|
4
|
-
"colors-bg-alternate": "var(--cdp-example-page-bg-alt-color)",
|
|
5
|
-
"colors-bg-default": "var(--cdp-example-
|
|
4
|
+
"colors-bg-alternate": "var(--cdp-example-cdp-page-bg-alt-color)",
|
|
5
|
+
"colors-bg-default": "var(--cdp-example-cdp-page-bg-color)",
|
|
6
6
|
"colors-bg-overlay": "var(--cdp-example-bg-overlay-color)",
|
|
7
7
|
"colors-bg-skeleton": "var(--cdp-example-bg-skeleton-color)",
|
|
8
8
|
"colors-bg-primary": "var(--cdp-example-accent-color)",
|
|
@@ -4,8 +4,11 @@ import {
|
|
|
4
4
|
useIsInitialized,
|
|
5
5
|
useSignInWithEmail,
|
|
6
6
|
useVerifyEmailOTP,
|
|
7
|
+
useSignInWithSms,
|
|
8
|
+
useVerifySmsOTP,
|
|
7
9
|
useIsSignedIn,
|
|
8
10
|
useSignOut,
|
|
11
|
+
useCurrentUser,
|
|
9
12
|
Config,
|
|
10
13
|
} from "@coinbase/cdp-hooks";
|
|
11
14
|
import { StatusBar } from "expo-status-bar";
|
|
@@ -15,13 +18,20 @@ import {
|
|
|
15
18
|
Text,
|
|
16
19
|
View,
|
|
17
20
|
TouchableOpacity,
|
|
18
|
-
TextInput,
|
|
19
21
|
Alert,
|
|
20
22
|
ScrollView,
|
|
21
23
|
SafeAreaView,
|
|
24
|
+
Animated,
|
|
25
|
+
Dimensions,
|
|
22
26
|
} from "react-native";
|
|
23
27
|
|
|
24
28
|
import Transaction from "./Transaction";
|
|
29
|
+
import { ThemeProvider, useTheme } from "./theme/ThemeContext";
|
|
30
|
+
import { WelcomeScreen } from "./components/WelcomeScreen";
|
|
31
|
+
import { SignInModal } from "./components/SignInModal";
|
|
32
|
+
import { DarkModeToggle } from "./components/DarkModeToggle";
|
|
33
|
+
import { WalletHeader } from "./components/WalletHeader";
|
|
34
|
+
import { AuthMethod } from "./types";
|
|
25
35
|
|
|
26
36
|
const cdpConfig: Config = {
|
|
27
37
|
projectId: process.env.EXPO_PUBLIC_CDP_PROJECT_ID,
|
|
@@ -31,15 +41,16 @@ const cdpConfig: Config = {
|
|
|
31
41
|
};
|
|
32
42
|
|
|
33
43
|
/**
|
|
34
|
-
* A multi-step authentication component that handles email-based sign-in
|
|
44
|
+
* A multi-step authentication component that handles email and SMS-based sign-in flows.
|
|
35
45
|
*
|
|
36
|
-
* The component manages
|
|
37
|
-
* 1. Initial state: Displays a welcome screen with
|
|
38
|
-
* 2.
|
|
39
|
-
* 3. OTP verification: Validates the one-time password sent to the user's email
|
|
46
|
+
* The component manages authentication states:
|
|
47
|
+
* 1. Initial state: Displays a welcome screen with sign-in options
|
|
48
|
+
* 2. Input: Collects and validates the user's email address or phone number
|
|
49
|
+
* 3. OTP verification: Validates the one-time password sent to the user's email or SMS
|
|
40
50
|
*
|
|
41
51
|
* Features:
|
|
42
|
-
* -
|
|
52
|
+
* - Toggle between email and SMS authentication
|
|
53
|
+
* - Email and phone number validation
|
|
43
54
|
* - 6-digit OTP validation
|
|
44
55
|
* - Loading states during API calls
|
|
45
56
|
* - Error handling for failed authentication attempts
|
|
@@ -52,46 +63,78 @@ function CDPApp() {
|
|
|
52
63
|
const { isSignedIn } = useIsSignedIn();
|
|
53
64
|
const { signInWithEmail } = useSignInWithEmail();
|
|
54
65
|
const { verifyEmailOTP } = useVerifyEmailOTP();
|
|
66
|
+
const { signInWithSms } = useSignInWithSms();
|
|
67
|
+
const { verifySmsOTP } = useVerifySmsOTP();
|
|
55
68
|
const { signOut } = useSignOut();
|
|
56
69
|
const { config } = useConfig();
|
|
70
|
+
const { colors, isDarkMode } = useTheme();
|
|
71
|
+
const { currentUser } = useCurrentUser();
|
|
57
72
|
|
|
73
|
+
const [authMethod, setAuthMethod] = useState<AuthMethod>("email");
|
|
58
74
|
const [email, setEmail] = useState("");
|
|
75
|
+
const [phoneNumber, setPhoneNumber] = useState("");
|
|
59
76
|
const [otp, setOtp] = useState("");
|
|
60
77
|
const [flowId, setFlowId] = useState("");
|
|
61
78
|
const [isLoading, setIsLoading] = useState(false);
|
|
79
|
+
const [showSignInModal, setShowSignInModal] = useState(false);
|
|
80
|
+
const [slideAnim] = useState(new Animated.Value(Dimensions.get("window").height));
|
|
62
81
|
|
|
63
82
|
const handleSignIn = async () => {
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
if (authMethod === "email") {
|
|
84
|
+
if (!email) {
|
|
85
|
+
Alert.alert("Error", "Please enter an email address.");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
68
88
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
89
|
+
setIsLoading(true);
|
|
90
|
+
try {
|
|
91
|
+
const result = await signInWithEmail({ email });
|
|
92
|
+
setFlowId(result.flowId);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
Alert.alert("Error", error instanceof Error ? error.message : "Failed to sign in.");
|
|
95
|
+
} finally {
|
|
96
|
+
setIsLoading(false);
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
if (!phoneNumber) {
|
|
100
|
+
Alert.alert("Error", "Please enter a phone number.");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
setIsLoading(true);
|
|
105
|
+
try {
|
|
106
|
+
// Format phone number with country code for SMS
|
|
107
|
+
const formattedPhoneNumber = phoneNumber.startsWith("+")
|
|
108
|
+
? phoneNumber
|
|
109
|
+
: `+1${phoneNumber.replace(/\D/g, "")}`;
|
|
110
|
+
const result = await signInWithSms({ phoneNumber: formattedPhoneNumber });
|
|
111
|
+
setFlowId(result.flowId);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
Alert.alert("Error", error instanceof Error ? error.message : "Failed to sign in.");
|
|
114
|
+
} finally {
|
|
115
|
+
setIsLoading(false);
|
|
116
|
+
}
|
|
78
117
|
}
|
|
79
118
|
};
|
|
80
119
|
|
|
81
120
|
const handleVerifyOTP = async () => {
|
|
82
121
|
if (!otp || !flowId) {
|
|
83
|
-
Alert.alert("Error", "Please enter the OTP");
|
|
122
|
+
Alert.alert("Error", "Please enter the OTP.");
|
|
84
123
|
return;
|
|
85
124
|
}
|
|
86
125
|
|
|
87
126
|
setIsLoading(true);
|
|
88
127
|
try {
|
|
89
|
-
|
|
90
|
-
|
|
128
|
+
if (authMethod === "email") {
|
|
129
|
+
await verifyEmailOTP({ flowId, otp });
|
|
130
|
+
} else {
|
|
131
|
+
await verifySmsOTP({ flowId, otp });
|
|
132
|
+
}
|
|
91
133
|
setOtp("");
|
|
92
134
|
setFlowId("");
|
|
135
|
+
closeSignInModal();
|
|
93
136
|
} catch (error) {
|
|
94
|
-
Alert.alert("Error", error instanceof Error ? error.message : "Failed to verify OTP");
|
|
137
|
+
Alert.alert("Error", error instanceof Error ? error.message : "Failed to verify OTP.");
|
|
95
138
|
} finally {
|
|
96
139
|
setIsLoading(false);
|
|
97
140
|
}
|
|
@@ -101,21 +144,111 @@ function CDPApp() {
|
|
|
101
144
|
try {
|
|
102
145
|
await signOut();
|
|
103
146
|
setEmail("");
|
|
147
|
+
setPhoneNumber("");
|
|
104
148
|
setOtp("");
|
|
105
149
|
setFlowId("");
|
|
106
|
-
Alert.alert("Success", "Signed out successfully");
|
|
107
150
|
} catch (error) {
|
|
108
|
-
Alert.alert("Error", error instanceof Error ? error.message : "Failed to sign out");
|
|
151
|
+
Alert.alert("Error", error instanceof Error ? error.message : "Failed to sign out.");
|
|
109
152
|
}
|
|
110
153
|
};
|
|
111
154
|
|
|
155
|
+
const handleAuthMethodToggle = () => {
|
|
156
|
+
setAuthMethod(authMethod === "email" ? "sms" : "email");
|
|
157
|
+
setEmail("");
|
|
158
|
+
setPhoneNumber("");
|
|
159
|
+
setOtp("");
|
|
160
|
+
setFlowId("");
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const openSignInModal = () => {
|
|
164
|
+
setShowSignInModal(true);
|
|
165
|
+
Animated.timing(slideAnim, {
|
|
166
|
+
toValue: 0,
|
|
167
|
+
duration: 300,
|
|
168
|
+
useNativeDriver: true,
|
|
169
|
+
}).start();
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const closeSignInModal = () => {
|
|
173
|
+
Animated.timing(slideAnim, {
|
|
174
|
+
toValue: Dimensions.get("window").height,
|
|
175
|
+
duration: 300,
|
|
176
|
+
useNativeDriver: true,
|
|
177
|
+
}).start(() => {
|
|
178
|
+
setShowSignInModal(false);
|
|
179
|
+
setEmail("");
|
|
180
|
+
setPhoneNumber("");
|
|
181
|
+
setOtp("");
|
|
182
|
+
setFlowId("");
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const createStyles = () =>
|
|
187
|
+
StyleSheet.create({
|
|
188
|
+
container: {
|
|
189
|
+
flex: 1,
|
|
190
|
+
backgroundColor: colors.background,
|
|
191
|
+
},
|
|
192
|
+
centerContent: {
|
|
193
|
+
flex: 1,
|
|
194
|
+
justifyContent: "center",
|
|
195
|
+
alignItems: "center",
|
|
196
|
+
padding: 20,
|
|
197
|
+
},
|
|
198
|
+
header: {
|
|
199
|
+
paddingHorizontal: 20,
|
|
200
|
+
paddingVertical: 16,
|
|
201
|
+
backgroundColor: colors.cardBackground,
|
|
202
|
+
borderBottomWidth: 1,
|
|
203
|
+
borderBottomColor: colors.border,
|
|
204
|
+
},
|
|
205
|
+
headerContent: {
|
|
206
|
+
flexDirection: "row",
|
|
207
|
+
alignItems: "center",
|
|
208
|
+
justifyContent: "space-between",
|
|
209
|
+
},
|
|
210
|
+
headerText: {
|
|
211
|
+
flex: 1,
|
|
212
|
+
alignItems: "flex-start",
|
|
213
|
+
paddingLeft: 4,
|
|
214
|
+
},
|
|
215
|
+
title: {
|
|
216
|
+
fontSize: 24,
|
|
217
|
+
fontWeight: "bold",
|
|
218
|
+
textAlign: "left",
|
|
219
|
+
color: colors.text,
|
|
220
|
+
},
|
|
221
|
+
text: {
|
|
222
|
+
fontSize: 16,
|
|
223
|
+
textAlign: "center",
|
|
224
|
+
color: colors.text,
|
|
225
|
+
},
|
|
226
|
+
content: {
|
|
227
|
+
flex: 1,
|
|
228
|
+
},
|
|
229
|
+
scrollView: {
|
|
230
|
+
flex: 1,
|
|
231
|
+
},
|
|
232
|
+
scrollContent: {
|
|
233
|
+
paddingVertical: 40,
|
|
234
|
+
paddingHorizontal: 20,
|
|
235
|
+
},
|
|
236
|
+
userContainer: {
|
|
237
|
+
width: "100%",
|
|
238
|
+
alignItems: "center",
|
|
239
|
+
marginBottom: 20,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
const styles = createStyles();
|
|
244
|
+
|
|
112
245
|
if (!isInitialized) {
|
|
113
246
|
return (
|
|
114
247
|
<SafeAreaView style={styles.container}>
|
|
115
248
|
<View style={styles.centerContent}>
|
|
116
249
|
<Text style={styles.text}>Initializing CDP...</Text>
|
|
117
250
|
</View>
|
|
118
|
-
<StatusBar style="
|
|
251
|
+
<StatusBar style={isDarkMode ? "light" : "dark"} />
|
|
119
252
|
</SafeAreaView>
|
|
120
253
|
);
|
|
121
254
|
}
|
|
@@ -123,78 +256,52 @@ function CDPApp() {
|
|
|
123
256
|
return (
|
|
124
257
|
<SafeAreaView style={styles.container}>
|
|
125
258
|
<View style={styles.header}>
|
|
126
|
-
<
|
|
127
|
-
|
|
259
|
+
<View style={styles.headerContent}>
|
|
260
|
+
<View style={styles.headerText}>
|
|
261
|
+
<Text style={styles.title}>CDP React Native Demo</Text>
|
|
262
|
+
</View>
|
|
263
|
+
<DarkModeToggle style={{ width: 40, height: 40 }} />
|
|
264
|
+
</View>
|
|
128
265
|
</View>
|
|
129
266
|
|
|
130
267
|
<View style={styles.content}>
|
|
131
268
|
{!isSignedIn ? (
|
|
132
|
-
<
|
|
133
|
-
<Text style={styles.label}>Email:</Text>
|
|
134
|
-
<TextInput
|
|
135
|
-
style={styles.input}
|
|
136
|
-
value={email}
|
|
137
|
-
onChangeText={setEmail}
|
|
138
|
-
placeholder="Enter your email"
|
|
139
|
-
keyboardType="email-address"
|
|
140
|
-
autoCapitalize="none"
|
|
141
|
-
autoCorrect={false}
|
|
142
|
-
editable={!isLoading}
|
|
143
|
-
/>
|
|
144
|
-
|
|
145
|
-
<TouchableOpacity
|
|
146
|
-
style={[styles.button, isLoading && styles.buttonDisabled]}
|
|
147
|
-
onPress={handleSignIn}
|
|
148
|
-
disabled={isLoading}
|
|
149
|
-
>
|
|
150
|
-
<Text style={styles.buttonText}>
|
|
151
|
-
{isLoading ? "Sending..." : "Sign In with Email"}
|
|
152
|
-
</Text>
|
|
153
|
-
</TouchableOpacity>
|
|
154
|
-
|
|
155
|
-
{flowId && (
|
|
156
|
-
<>
|
|
157
|
-
<Text style={styles.label}>Enter OTP from email:</Text>
|
|
158
|
-
<TextInput
|
|
159
|
-
style={styles.input}
|
|
160
|
-
value={otp}
|
|
161
|
-
onChangeText={setOtp}
|
|
162
|
-
placeholder="Enter 6-digit OTP"
|
|
163
|
-
keyboardType="number-pad"
|
|
164
|
-
maxLength={6}
|
|
165
|
-
editable={!isLoading}
|
|
166
|
-
/>
|
|
167
|
-
|
|
168
|
-
<TouchableOpacity
|
|
169
|
-
style={[styles.button, isLoading && styles.buttonDisabled]}
|
|
170
|
-
onPress={handleVerifyOTP}
|
|
171
|
-
disabled={isLoading}
|
|
172
|
-
>
|
|
173
|
-
<Text style={styles.buttonText}>{isLoading ? "Verifying..." : "Verify OTP"}</Text>
|
|
174
|
-
</TouchableOpacity>
|
|
175
|
-
</>
|
|
176
|
-
)}
|
|
177
|
-
</View>
|
|
269
|
+
<WelcomeScreen onSignInPress={openSignInModal} />
|
|
178
270
|
) : (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
</TouchableOpacity>
|
|
192
|
-
</View>
|
|
193
|
-
</ScrollView>
|
|
271
|
+
<>
|
|
272
|
+
<WalletHeader onSignOut={handleSignOut} />
|
|
273
|
+
<ScrollView
|
|
274
|
+
style={styles.scrollView}
|
|
275
|
+
showsVerticalScrollIndicator={false}
|
|
276
|
+
contentContainerStyle={styles.scrollContent}
|
|
277
|
+
>
|
|
278
|
+
<View style={styles.userContainer}>
|
|
279
|
+
<Transaction onSuccess={() => console.log("Transaction successful!")} />
|
|
280
|
+
</View>
|
|
281
|
+
</ScrollView>
|
|
282
|
+
</>
|
|
194
283
|
)}
|
|
195
284
|
</View>
|
|
196
285
|
|
|
197
|
-
<
|
|
286
|
+
<SignInModal
|
|
287
|
+
visible={showSignInModal}
|
|
288
|
+
onClose={closeSignInModal}
|
|
289
|
+
authMethod={authMethod}
|
|
290
|
+
onAuthMethodToggle={handleAuthMethodToggle}
|
|
291
|
+
email={email}
|
|
292
|
+
setEmail={setEmail}
|
|
293
|
+
phoneNumber={phoneNumber}
|
|
294
|
+
setPhoneNumber={setPhoneNumber}
|
|
295
|
+
otp={otp}
|
|
296
|
+
setOtp={setOtp}
|
|
297
|
+
flowId={flowId}
|
|
298
|
+
isLoading={isLoading}
|
|
299
|
+
onSignIn={handleSignIn}
|
|
300
|
+
onVerifyOTP={handleVerifyOTP}
|
|
301
|
+
slideAnim={slideAnim}
|
|
302
|
+
/>
|
|
303
|
+
|
|
304
|
+
<StatusBar style={isDarkMode ? "light" : "dark"} />
|
|
198
305
|
</SafeAreaView>
|
|
199
306
|
);
|
|
200
307
|
}
|
|
@@ -207,153 +314,9 @@ function CDPApp() {
|
|
|
207
314
|
export default function App() {
|
|
208
315
|
return (
|
|
209
316
|
<CDPHooksProvider config={cdpConfig}>
|
|
210
|
-
<
|
|
317
|
+
<ThemeProvider>
|
|
318
|
+
<CDPApp />
|
|
319
|
+
</ThemeProvider>
|
|
211
320
|
</CDPHooksProvider>
|
|
212
321
|
);
|
|
213
322
|
}
|
|
214
|
-
|
|
215
|
-
const styles = StyleSheet.create({
|
|
216
|
-
container: {
|
|
217
|
-
flex: 1,
|
|
218
|
-
backgroundColor: "#eaeaea",
|
|
219
|
-
},
|
|
220
|
-
centerContent: {
|
|
221
|
-
flex: 1,
|
|
222
|
-
justifyContent: "center",
|
|
223
|
-
alignItems: "center",
|
|
224
|
-
padding: 20,
|
|
225
|
-
},
|
|
226
|
-
header: {
|
|
227
|
-
paddingHorizontal: 20,
|
|
228
|
-
paddingVertical: 16,
|
|
229
|
-
backgroundColor: "#ffffff",
|
|
230
|
-
alignItems: "center",
|
|
231
|
-
borderBottomWidth: 1,
|
|
232
|
-
borderBottomColor: "#dcdcdc",
|
|
233
|
-
},
|
|
234
|
-
content: {
|
|
235
|
-
flex: 1,
|
|
236
|
-
paddingHorizontal: 20,
|
|
237
|
-
justifyContent: "center",
|
|
238
|
-
},
|
|
239
|
-
scrollView: {
|
|
240
|
-
flex: 1,
|
|
241
|
-
},
|
|
242
|
-
scrollContent: {
|
|
243
|
-
paddingVertical: 20,
|
|
244
|
-
},
|
|
245
|
-
title: {
|
|
246
|
-
fontSize: 24,
|
|
247
|
-
fontWeight: "bold",
|
|
248
|
-
marginBottom: 10,
|
|
249
|
-
textAlign: "center",
|
|
250
|
-
color: "#111111",
|
|
251
|
-
},
|
|
252
|
-
subtitle: {
|
|
253
|
-
fontSize: 14,
|
|
254
|
-
color: "#757575",
|
|
255
|
-
marginBottom: 30,
|
|
256
|
-
textAlign: "center",
|
|
257
|
-
},
|
|
258
|
-
text: {
|
|
259
|
-
fontSize: 16,
|
|
260
|
-
textAlign: "center",
|
|
261
|
-
color: "#111111",
|
|
262
|
-
},
|
|
263
|
-
authContainer: {
|
|
264
|
-
width: "100%",
|
|
265
|
-
maxWidth: 300,
|
|
266
|
-
alignSelf: "center",
|
|
267
|
-
},
|
|
268
|
-
userContainer: {
|
|
269
|
-
width: "100%",
|
|
270
|
-
alignItems: "center",
|
|
271
|
-
marginBottom: 20,
|
|
272
|
-
},
|
|
273
|
-
copyableInfoContainer: {
|
|
274
|
-
width: "100%",
|
|
275
|
-
marginBottom: 16,
|
|
276
|
-
alignItems: "center",
|
|
277
|
-
},
|
|
278
|
-
infoLabel: {
|
|
279
|
-
fontSize: 14,
|
|
280
|
-
fontWeight: "600",
|
|
281
|
-
color: "#757575",
|
|
282
|
-
marginBottom: 6,
|
|
283
|
-
textAlign: "center",
|
|
284
|
-
},
|
|
285
|
-
copyableInfo: {
|
|
286
|
-
backgroundColor: "rgba(0, 128, 128, 0.1)",
|
|
287
|
-
borderRadius: 8,
|
|
288
|
-
padding: 12,
|
|
289
|
-
borderWidth: 1,
|
|
290
|
-
borderColor: "rgba(0, 128, 128, 0.3)",
|
|
291
|
-
width: "100%",
|
|
292
|
-
maxWidth: 280,
|
|
293
|
-
},
|
|
294
|
-
copyableText: {
|
|
295
|
-
fontSize: 12,
|
|
296
|
-
fontFamily: "monospace",
|
|
297
|
-
color: "#008080",
|
|
298
|
-
textAlign: "center",
|
|
299
|
-
marginBottom: 4,
|
|
300
|
-
},
|
|
301
|
-
copyHint: {
|
|
302
|
-
fontSize: 10,
|
|
303
|
-
color: "#008080",
|
|
304
|
-
fontStyle: "italic",
|
|
305
|
-
textAlign: "center",
|
|
306
|
-
},
|
|
307
|
-
welcomeText: {
|
|
308
|
-
fontSize: 20,
|
|
309
|
-
fontWeight: "bold",
|
|
310
|
-
marginBottom: 20,
|
|
311
|
-
textAlign: "center",
|
|
312
|
-
color: "#111111",
|
|
313
|
-
},
|
|
314
|
-
userInfo: {
|
|
315
|
-
fontSize: 14,
|
|
316
|
-
marginBottom: 8,
|
|
317
|
-
textAlign: "center",
|
|
318
|
-
color: "#111111",
|
|
319
|
-
},
|
|
320
|
-
label: {
|
|
321
|
-
fontSize: 16,
|
|
322
|
-
fontWeight: "500",
|
|
323
|
-
marginBottom: 8,
|
|
324
|
-
color: "#111111",
|
|
325
|
-
},
|
|
326
|
-
input: {
|
|
327
|
-
borderWidth: 1,
|
|
328
|
-
borderColor: "#dcdcdc",
|
|
329
|
-
borderRadius: 8,
|
|
330
|
-
padding: 12,
|
|
331
|
-
fontSize: 16,
|
|
332
|
-
marginBottom: 16,
|
|
333
|
-
backgroundColor: "#ffffff",
|
|
334
|
-
color: "#111111",
|
|
335
|
-
},
|
|
336
|
-
button: {
|
|
337
|
-
backgroundColor: "#008080",
|
|
338
|
-
padding: 15,
|
|
339
|
-
borderRadius: 8,
|
|
340
|
-
alignItems: "center",
|
|
341
|
-
marginBottom: 12,
|
|
342
|
-
},
|
|
343
|
-
buttonDisabled: {
|
|
344
|
-
opacity: 0.6,
|
|
345
|
-
},
|
|
346
|
-
buttonText: {
|
|
347
|
-
color: "#ffffff",
|
|
348
|
-
fontSize: 16,
|
|
349
|
-
fontWeight: "600",
|
|
350
|
-
},
|
|
351
|
-
signOutButton: {
|
|
352
|
-
backgroundColor: "#f44336",
|
|
353
|
-
padding: 15,
|
|
354
|
-
borderRadius: 8,
|
|
355
|
-
alignItems: "center",
|
|
356
|
-
marginTop: 20,
|
|
357
|
-
width: "100%",
|
|
358
|
-
},
|
|
359
|
-
});
|