create-better-t-stack 3.1.8 → 3.2.1
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/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-DeOVz-ZI.js → src-DaKmcEvQ.js} +75 -19
- package/package.json +1 -1
- package/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs +55 -34
- package/templates/auth/better-auth/convex/backend/convex/http.ts.hbs +1 -1
- package/templates/auth/better-auth/convex/native/base/lib/auth-client.ts.hbs +19 -0
- package/templates/auth/better-auth/convex/native/nativewind/components/sign-in.tsx.hbs +86 -0
- package/templates/auth/better-auth/convex/native/nativewind/components/sign-up.tsx.hbs +97 -0
- package/templates/auth/better-auth/convex/native/unistyles/components/sign-in.tsx.hbs +127 -0
- package/templates/auth/better-auth/convex/native/unistyles/components/sign-up.tsx.hbs +145 -0
- package/templates/auth/better-auth/native/{native-base → base}/lib/auth-client.ts.hbs +3 -2
- package/templates/frontend/native/nativewind/app/(drawer)/index.tsx.hbs +127 -76
- package/templates/frontend/native/nativewind/app/_layout.tsx.hbs +21 -0
- package/templates/frontend/native/unistyles/app/(drawer)/index.tsx.hbs +160 -51
- package/templates/frontend/native/unistyles/app/_layout.tsx.hbs +28 -0
- package/templates/frontend/native/unistyles/app.json.hbs +1 -1
- /package/templates/frontend/native/{native-base → base}/assets/images/android-icon-background.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/android-icon-foreground.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/android-icon-monochrome.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/favicon.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/icon.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/partial-react-logo.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/react-logo.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/react-logo@2x.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/react-logo@3x.png +0 -0
- /package/templates/frontend/native/{native-base → base}/assets/images/splash-icon.png +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { authClient } from "@/lib/auth-client";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import {
|
|
4
|
+
ActivityIndicator,
|
|
5
|
+
Text,
|
|
6
|
+
TextInput,
|
|
7
|
+
TouchableOpacity,
|
|
8
|
+
View,
|
|
9
|
+
} from "react-native";
|
|
10
|
+
import { StyleSheet } from "react-native-unistyles";
|
|
11
|
+
|
|
12
|
+
export function SignUp() {
|
|
13
|
+
const [name, setName] = useState("");
|
|
14
|
+
const [email, setEmail] = useState("");
|
|
15
|
+
const [password, setPassword] = useState("");
|
|
16
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
17
|
+
const [error, setError] = useState<string | null>(null);
|
|
18
|
+
|
|
19
|
+
const handleSignUp = async () => {
|
|
20
|
+
setIsLoading(true);
|
|
21
|
+
setError(null);
|
|
22
|
+
|
|
23
|
+
await authClient.signUp.email(
|
|
24
|
+
{
|
|
25
|
+
name,
|
|
26
|
+
email,
|
|
27
|
+
password,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
onError: (error) => {
|
|
31
|
+
setError(error.error?.message || "Failed to sign up");
|
|
32
|
+
setIsLoading(false);
|
|
33
|
+
},
|
|
34
|
+
onSuccess: () => {
|
|
35
|
+
setName("");
|
|
36
|
+
setEmail("");
|
|
37
|
+
setPassword("");
|
|
38
|
+
},
|
|
39
|
+
onFinished: () => {
|
|
40
|
+
setIsLoading(false);
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<View style={styles.container}>
|
|
48
|
+
<Text style={styles.title}>Create Account</Text>
|
|
49
|
+
|
|
50
|
+
{error && (
|
|
51
|
+
<View style={styles.errorContainer}>
|
|
52
|
+
<Text style={styles.errorText}>{error}</Text>
|
|
53
|
+
</View>
|
|
54
|
+
)}
|
|
55
|
+
|
|
56
|
+
<TextInput
|
|
57
|
+
style={styles.input}
|
|
58
|
+
placeholder="Name"
|
|
59
|
+
value={name}
|
|
60
|
+
onChangeText={setName}
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
<TextInput
|
|
64
|
+
style={styles.input}
|
|
65
|
+
placeholder="Email"
|
|
66
|
+
value={email}
|
|
67
|
+
onChangeText={setEmail}
|
|
68
|
+
keyboardType="email-address"
|
|
69
|
+
autoCapitalize="none"
|
|
70
|
+
/>
|
|
71
|
+
|
|
72
|
+
<TextInput
|
|
73
|
+
style={styles.inputLast}
|
|
74
|
+
placeholder="Password"
|
|
75
|
+
value={password}
|
|
76
|
+
onChangeText={setPassword}
|
|
77
|
+
secureTextEntry
|
|
78
|
+
/>
|
|
79
|
+
|
|
80
|
+
<TouchableOpacity
|
|
81
|
+
onPress={handleSignUp}
|
|
82
|
+
disabled={isLoading}
|
|
83
|
+
style={styles.button}
|
|
84
|
+
>
|
|
85
|
+
{isLoading ? (
|
|
86
|
+
<ActivityIndicator size="small" color="#fff" />
|
|
87
|
+
) : (
|
|
88
|
+
<Text style={styles.buttonText}>Sign Up</Text>
|
|
89
|
+
)}
|
|
90
|
+
</TouchableOpacity>
|
|
91
|
+
</View>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const styles = StyleSheet.create((theme) => ({
|
|
96
|
+
container: {
|
|
97
|
+
marginTop: 24,
|
|
98
|
+
padding: 16,
|
|
99
|
+
borderRadius: 8,
|
|
100
|
+
borderWidth: 1,
|
|
101
|
+
borderColor: theme.colors.border,
|
|
102
|
+
},
|
|
103
|
+
title: {
|
|
104
|
+
fontSize: 18,
|
|
105
|
+
fontWeight: "600",
|
|
106
|
+
color: theme.colors.typography,
|
|
107
|
+
marginBottom: 16,
|
|
108
|
+
},
|
|
109
|
+
errorContainer: {
|
|
110
|
+
marginBottom: 16,
|
|
111
|
+
padding: 12,
|
|
112
|
+
borderRadius: 6,
|
|
113
|
+
},
|
|
114
|
+
errorText: {
|
|
115
|
+
color: theme.colors.destructive,
|
|
116
|
+
fontSize: 14,
|
|
117
|
+
},
|
|
118
|
+
input: {
|
|
119
|
+
marginBottom: 12,
|
|
120
|
+
padding: 16,
|
|
121
|
+
borderRadius: 6,
|
|
122
|
+
color: theme.colors.typography,
|
|
123
|
+
borderWidth: 1,
|
|
124
|
+
borderColor: theme.colors.border,
|
|
125
|
+
},
|
|
126
|
+
inputLast: {
|
|
127
|
+
marginBottom: 16,
|
|
128
|
+
padding: 16,
|
|
129
|
+
borderRadius: 6,
|
|
130
|
+
color: theme.colors.typography,
|
|
131
|
+
borderWidth: 1,
|
|
132
|
+
borderColor: theme.colors.border,
|
|
133
|
+
},
|
|
134
|
+
button: {
|
|
135
|
+
backgroundColor: theme.colors.primary,
|
|
136
|
+
padding: 16,
|
|
137
|
+
borderRadius: 6,
|
|
138
|
+
flexDirection: "row",
|
|
139
|
+
justifyContent: "center",
|
|
140
|
+
alignItems: "center",
|
|
141
|
+
},
|
|
142
|
+
buttonText: {
|
|
143
|
+
fontWeight: "500",
|
|
144
|
+
},
|
|
145
|
+
}));
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { expoClient } from "@better-auth/expo/client";
|
|
2
2
|
import { createAuthClient } from "better-auth/react";
|
|
3
3
|
import * as SecureStore from "expo-secure-store";
|
|
4
|
+
import Constants from "expo-constants";
|
|
4
5
|
|
|
5
6
|
export const authClient = createAuthClient({
|
|
6
7
|
baseURL: process.env.EXPO_PUBLIC_SERVER_URL,
|
|
7
8
|
plugins: [
|
|
8
9
|
expoClient({
|
|
9
|
-
|
|
10
|
-
storagePrefix:
|
|
10
|
+
scheme: Constants.expoConfig?.scheme as string,
|
|
11
|
+
storagePrefix: Constants.expoConfig?.scheme as string,
|
|
11
12
|
storage: SecureStore,
|
|
12
13
|
}),
|
|
13
14
|
],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { View, Text, ScrollView } from "react-native";
|
|
1
|
+
import { View, Text, ScrollView, TouchableOpacity } from "react-native";
|
|
2
2
|
import { Container } from "@/components/container";
|
|
3
3
|
{{#if (eq api "orpc")}}
|
|
4
4
|
import { useQuery } from "@tanstack/react-query";
|
|
@@ -8,18 +8,22 @@ import { orpc } from "@/utils/orpc";
|
|
|
8
8
|
import { useQuery } from "@tanstack/react-query";
|
|
9
9
|
import { trpc } from "@/utils/trpc";
|
|
10
10
|
{{/if}}
|
|
11
|
-
{{#if (eq backend "convex")}}
|
|
12
|
-
{{#if (eq auth "clerk")}}
|
|
11
|
+
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
13
12
|
import { Link } from "expo-router";
|
|
14
13
|
import { Authenticated, AuthLoading, Unauthenticated, useQuery } from "convex/react";
|
|
15
14
|
import { api } from "@{{ projectName }}/backend/convex/_generated/api";
|
|
16
15
|
import { useUser } from "@clerk/clerk-expo";
|
|
17
16
|
import { SignOutButton } from "@/components/sign-out-button";
|
|
18
|
-
{{else}}
|
|
17
|
+
{{else if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
18
|
+
import { useConvexAuth, useQuery } from "convex/react";
|
|
19
|
+
import { api } from "@{{ projectName }}/backend/convex/_generated/api";
|
|
20
|
+
import { authClient } from "@/lib/auth-client";
|
|
21
|
+
import { SignIn } from "@/components/sign-in";
|
|
22
|
+
import { SignUp } from "@/components/sign-up";
|
|
23
|
+
{{else if (eq backend "convex")}}
|
|
19
24
|
import { useQuery } from "convex/react";
|
|
20
25
|
import { api } from "@{{ projectName }}/backend/convex/_generated/api";
|
|
21
26
|
{{/if}}
|
|
22
|
-
{{/if}}
|
|
23
27
|
|
|
24
28
|
export default function Home() {
|
|
25
29
|
{{#if (eq api "orpc")}}
|
|
@@ -28,100 +32,147 @@ export default function Home() {
|
|
|
28
32
|
{{#if (eq api "trpc")}}
|
|
29
33
|
const healthCheck = useQuery(trpc.healthCheck.queryOptions());
|
|
30
34
|
{{/if}}
|
|
31
|
-
{{#if (eq backend "convex")}}
|
|
32
|
-
{{#if (eq auth "clerk")}}
|
|
35
|
+
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
33
36
|
const { user } = useUser();
|
|
34
37
|
const healthCheck = useQuery(api.healthCheck.get);
|
|
35
38
|
const privateData = useQuery(api.privateData.get);
|
|
36
|
-
{{else}}
|
|
39
|
+
{{else if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
40
|
+
const healthCheck = useQuery(api.healthCheck.get);
|
|
41
|
+
const { isAuthenticated } = useConvexAuth();
|
|
42
|
+
const user = useQuery(api.auth.getCurrentUser, isAuthenticated ? {} : "skip");
|
|
43
|
+
{{else if (eq backend "convex")}}
|
|
37
44
|
const healthCheck = useQuery(api.healthCheck.get);
|
|
38
|
-
{{/if}}
|
|
39
45
|
{{/if}}
|
|
40
46
|
|
|
41
47
|
return (
|
|
42
48
|
<Container>
|
|
43
|
-
<ScrollView
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
<ScrollView className="flex-1">
|
|
50
|
+
<View className="px-4">
|
|
51
|
+
<Text className="font-mono text-foreground text-3xl font-bold mb-4">
|
|
52
|
+
BETTER T STACK
|
|
53
|
+
</Text>
|
|
54
|
+
|
|
55
|
+
{{#unless (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
56
|
+
<View className="bg-card border border-border rounded-xl p-6 mb-6 shadow-sm">
|
|
57
|
+
{{#if (eq backend "convex")}}
|
|
58
|
+
<View className="flex-row items-center gap-3">
|
|
59
|
+
<View
|
|
60
|
+
className={`h-3 w-3 rounded-full ${
|
|
61
|
+
healthCheck ? "bg-green-500" : "bg-orange-500"
|
|
62
|
+
}`}
|
|
63
|
+
/>
|
|
64
|
+
<View className="flex-1">
|
|
65
|
+
<Text className="text-sm font-medium text-card-foreground">
|
|
66
|
+
Convex
|
|
67
|
+
</Text>
|
|
68
|
+
<Text className="text-muted-foreground">
|
|
69
|
+
{
|
|
70
|
+
healthCheck === undefined
|
|
71
|
+
? "Checking..."
|
|
72
|
+
: healthCheck === "OK"
|
|
73
|
+
? "Connected to API"
|
|
74
|
+
: "API Disconnected"
|
|
75
|
+
}
|
|
76
|
+
</Text>
|
|
77
|
+
</View>
|
|
78
|
+
</View>
|
|
79
|
+
{{else}}
|
|
80
|
+
{{#unless (eq api "none")}}
|
|
81
|
+
<View className="flex-row items-center gap-3">
|
|
82
|
+
<View
|
|
83
|
+
className={`h-3 w-3 rounded-full ${
|
|
84
|
+
healthCheck.data ? "bg-green-500" : "bg-orange-500"
|
|
85
|
+
}`}
|
|
86
|
+
/>
|
|
55
87
|
<View className="flex-1">
|
|
56
88
|
<Text className="text-sm font-medium text-card-foreground">
|
|
57
|
-
|
|
89
|
+
{{#if (eq api "orpc")}}ORPC{{else}}TRPC{{/if}}
|
|
58
90
|
</Text>
|
|
59
91
|
<Text className="text-xs text-muted-foreground">
|
|
60
|
-
{healthCheck
|
|
92
|
+
{healthCheck.isLoading
|
|
61
93
|
? "Checking connection..."
|
|
62
|
-
: healthCheck
|
|
63
|
-
|
|
64
|
-
|
|
94
|
+
: healthCheck.data
|
|
95
|
+
? "All systems operational"
|
|
96
|
+
: "Service unavailable"}
|
|
65
97
|
</Text>
|
|
66
98
|
</View>
|
|
99
|
+
</View>
|
|
100
|
+
{{/unless}}
|
|
101
|
+
{{/if}}
|
|
67
102
|
</View>
|
|
68
|
-
{{
|
|
69
|
-
|
|
70
|
-
|
|
103
|
+
{{/unless}}
|
|
104
|
+
|
|
105
|
+
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
106
|
+
<Authenticated>
|
|
107
|
+
<Text>Hello {user?.emailAddresses[0].emailAddress}</Text>
|
|
108
|
+
<Text>Private Data: {privateData?.message}</Text>
|
|
109
|
+
<SignOutButton />
|
|
110
|
+
</Authenticated>
|
|
111
|
+
<Unauthenticated>
|
|
112
|
+
<Link href="/(auth)/sign-in">
|
|
113
|
+
<Text>Sign in</Text>
|
|
114
|
+
</Link>
|
|
115
|
+
<Link href="/(auth)/sign-up">
|
|
116
|
+
<Text>Sign up</Text>
|
|
117
|
+
</Link>
|
|
118
|
+
</Unauthenticated>
|
|
119
|
+
<AuthLoading>
|
|
120
|
+
<Text>Loading...</Text>
|
|
121
|
+
</AuthLoading>
|
|
122
|
+
{{/if}}
|
|
123
|
+
|
|
124
|
+
{{#if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
125
|
+
{user ? (
|
|
126
|
+
<View className="mb-6 p-4 bg-card rounded-lg border border-border">
|
|
127
|
+
<View className="flex-row justify-between items-center mb-2">
|
|
128
|
+
<Text className="text-foreground text-base">
|
|
129
|
+
Welcome,{" "}
|
|
130
|
+
<Text className="font-medium">{user.name}</Text>
|
|
131
|
+
</Text>
|
|
132
|
+
</View>
|
|
133
|
+
<Text className="text-muted-foreground text-sm mb-4">
|
|
134
|
+
{user.email}
|
|
135
|
+
</Text>
|
|
136
|
+
<TouchableOpacity
|
|
137
|
+
className="bg-destructive py-2 px-4 rounded-md self-start"
|
|
138
|
+
onPress={() => {
|
|
139
|
+
authClient.signOut();
|
|
140
|
+
}}
|
|
141
|
+
>
|
|
142
|
+
<Text className="text-white font-medium">Sign Out</Text>
|
|
143
|
+
</TouchableOpacity>
|
|
144
|
+
</View>
|
|
145
|
+
) : null}
|
|
146
|
+
<View className="mb-6 rounded-lg border border-border p-4">
|
|
147
|
+
<Text className="mb-3 font-medium text-foreground">
|
|
148
|
+
API Status
|
|
149
|
+
</Text>
|
|
150
|
+
<View className="flex-row items-center gap-2">
|
|
71
151
|
<View
|
|
72
152
|
className={`h-3 w-3 rounded-full ${
|
|
73
|
-
|
|
153
|
+
healthCheck ? "bg-green-500" : "bg-red-500"
|
|
74
154
|
}`}
|
|
75
155
|
/>
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<Text className="text-xs text-muted-foreground">
|
|
86
|
-
{{#if (eq api "orpc")}}
|
|
87
|
-
{healthCheck.isLoading
|
|
88
|
-
? "Checking connection..."
|
|
89
|
-
: healthCheck.data
|
|
90
|
-
? "All systems operational"
|
|
91
|
-
: "Service unavailable"}
|
|
92
|
-
{{/if}}
|
|
93
|
-
{{#if (eq api "trpc")}}
|
|
94
|
-
{healthCheck.isLoading
|
|
95
|
-
? "Checking connection..."
|
|
96
|
-
: healthCheck.data
|
|
97
|
-
? "All systems operational"
|
|
98
|
-
: "Service unavailable"}
|
|
99
|
-
{{/if}}
|
|
100
|
-
</Text>
|
|
101
|
-
</View>
|
|
156
|
+
<Text className="text-muted-foreground">
|
|
157
|
+
{
|
|
158
|
+
healthCheck === undefined
|
|
159
|
+
? "Checking..."
|
|
160
|
+
: healthCheck === "OK"
|
|
161
|
+
? "Connected to API"
|
|
162
|
+
: "API Disconnected"
|
|
163
|
+
}
|
|
164
|
+
</Text>
|
|
102
165
|
</View>
|
|
103
|
-
|
|
166
|
+
</View>
|
|
167
|
+
{!user && (
|
|
168
|
+
<>
|
|
169
|
+
<SignIn />
|
|
170
|
+
<SignUp />
|
|
171
|
+
</>
|
|
172
|
+
)}
|
|
104
173
|
{{/if}}
|
|
105
174
|
</View>
|
|
106
|
-
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
107
|
-
<Authenticated>
|
|
108
|
-
<Text>Hello {user?.emailAddresses[0].emailAddress}</Text>
|
|
109
|
-
<Text>Private Data: {privateData?.message}</Text>
|
|
110
|
-
<SignOutButton />
|
|
111
|
-
</Authenticated>
|
|
112
|
-
<Unauthenticated>
|
|
113
|
-
<Link href="/(auth)/sign-in">
|
|
114
|
-
<Text>Sign in</Text>
|
|
115
|
-
</Link>
|
|
116
|
-
<Link href="/(auth)/sign-up">
|
|
117
|
-
<Text>Sign up</Text>
|
|
118
|
-
</Link>
|
|
119
|
-
</Unauthenticated>
|
|
120
|
-
<AuthLoading>
|
|
121
|
-
<Text>Loading...</Text>
|
|
122
|
-
</AuthLoading>
|
|
123
|
-
{{/if}}
|
|
124
175
|
</ScrollView>
|
|
125
176
|
</Container>
|
|
126
177
|
);
|
|
127
|
-
}
|
|
178
|
+
}
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
import "@/polyfills";
|
|
3
3
|
{{/if}}
|
|
4
4
|
{{#if (eq backend "convex")}}
|
|
5
|
+
{{#if (eq auth "better-auth")}}
|
|
6
|
+
import { ConvexReactClient } from "convex/react";
|
|
7
|
+
import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react";
|
|
8
|
+
import { authClient } from "@/lib/auth-client";
|
|
9
|
+
{{else}}
|
|
5
10
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
|
11
|
+
{{/if}}
|
|
6
12
|
{{#if (eq auth "clerk")}}
|
|
7
13
|
import { ClerkProvider, useAuth } from "@clerk/clerk-expo";
|
|
8
14
|
import { ConvexProviderWithClerk } from "convex/react-clerk";
|
|
@@ -98,6 +104,21 @@ export default function RootLayout() {
|
|
|
98
104
|
</ThemeProvider>
|
|
99
105
|
</ConvexProviderWithClerk>
|
|
100
106
|
</ClerkProvider>
|
|
107
|
+
{{else if (eq auth "better-auth")}}
|
|
108
|
+
<ConvexBetterAuthProvider client={convex} authClient={authClient}>
|
|
109
|
+
<ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
|
|
110
|
+
<StatusBar style={isDarkColorScheme ? "light" : "dark"} />
|
|
111
|
+
<GestureHandlerRootView style=\{{ flex: 1 }}>
|
|
112
|
+
<Stack>
|
|
113
|
+
<Stack.Screen name="(drawer)" options=\{{ headerShown: false }} />
|
|
114
|
+
<Stack.Screen
|
|
115
|
+
name="modal"
|
|
116
|
+
options=\{{ title: "Modal", presentation: "modal" }}
|
|
117
|
+
/>
|
|
118
|
+
</Stack>
|
|
119
|
+
</GestureHandlerRootView>
|
|
120
|
+
</ThemeProvider>
|
|
121
|
+
</ConvexBetterAuthProvider>
|
|
101
122
|
{{else}}
|
|
102
123
|
<ConvexProvider client={convex}>
|
|
103
124
|
<ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
|