social login
implemented, we can add more providers later
This commit is contained in:
parent
8b4cef33dc
commit
a96f1902c5
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useSignIn, useAuth } from "@clerk/clerk-expo";
|
import { useSignIn, useAuth } from "@clerk/clerk-expo";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
import {
|
import {
|
||||||
@ -12,19 +12,20 @@ import {
|
|||||||
Platform,
|
Platform,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
|
import { OAuthButtons } from "../../components/auth/OAuthButtons";
|
||||||
|
|
||||||
export default function SignInScreen() {
|
export default function SignInScreen() {
|
||||||
const { signIn, setActive, isLoaded } = useSignIn();
|
const { signIn, setActive, isLoaded } = useSignIn();
|
||||||
const { isSignedIn } = useAuth();
|
const { isSignedIn } = useAuth();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const [emailAddress, setEmailAddress] = React.useState("");
|
const [emailAddress, setEmailAddress] = useState("");
|
||||||
const [password, setPassword] = React.useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = React.useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
// Redirect if already signed in
|
// Redirect if already signed in
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSignedIn) {
|
if (isSignedIn) {
|
||||||
router.replace("/(tabs)");
|
router.replace("/(tabs)");
|
||||||
}
|
}
|
||||||
@ -100,6 +101,14 @@ export default function SignInScreen() {
|
|||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
<OAuthButtons />
|
||||||
|
|
||||||
|
<View style={styles.dividerContainer}>
|
||||||
|
<View style={styles.dividerLine} />
|
||||||
|
<Text style={styles.dividerText}>OR</Text>
|
||||||
|
<View style={styles.dividerLine} />
|
||||||
|
</View>
|
||||||
|
|
||||||
<View style={styles.form}>
|
<View style={styles.form}>
|
||||||
<View style={styles.inputContainer}>
|
<View style={styles.inputContainer}>
|
||||||
<Text style={styles.label}>Email</Text>
|
<Text style={styles.label}>Email</Text>
|
||||||
@ -256,4 +265,19 @@ const styles = StyleSheet.create({
|
|||||||
color: "#2563eb",
|
color: "#2563eb",
|
||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
},
|
},
|
||||||
|
dividerContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
dividerLine: {
|
||||||
|
flex: 1,
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: "#ddd",
|
||||||
|
},
|
||||||
|
dividerText: {
|
||||||
|
marginHorizontal: 10,
|
||||||
|
color: "#666",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useSignUp, useAuth } from "@clerk/clerk-expo";
|
import { useSignUp, useAuth } from "@clerk/clerk-expo";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
import {
|
import {
|
||||||
@ -12,23 +12,24 @@ import {
|
|||||||
Platform,
|
Platform,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
|
import { OAuthButtons } from "../../components/auth/OAuthButtons";
|
||||||
|
|
||||||
export default function SignUpScreen() {
|
export default function SignUpScreen() {
|
||||||
const { signUp, setActive, isLoaded } = useSignUp();
|
const { signUp, setActive, isLoaded } = useSignUp();
|
||||||
const { isSignedIn } = useAuth();
|
const { isSignedIn } = useAuth();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const [emailAddress, setEmailAddress] = React.useState("");
|
const [emailAddress, setEmailAddress] = useState("");
|
||||||
const [password, setPassword] = React.useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [firstName, setFirstName] = React.useState("");
|
const [firstName, setFirstName] = useState("");
|
||||||
const [lastName, setLastName] = React.useState("");
|
const [lastName, setLastName] = useState("");
|
||||||
const [pendingVerification, setPendingVerification] = React.useState(false);
|
const [pendingVerification, setPendingVerification] = useState(false);
|
||||||
const [code, setCode] = React.useState("");
|
const [code, setCode] = useState("");
|
||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = React.useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
// Redirect if already signed in
|
// Redirect if already signed in
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSignedIn) {
|
if (isSignedIn) {
|
||||||
router.replace("/(tabs)");
|
router.replace("/(tabs)");
|
||||||
}
|
}
|
||||||
@ -182,6 +183,14 @@ export default function SignUpScreen() {
|
|||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
<OAuthButtons />
|
||||||
|
|
||||||
|
<View style={styles.dividerContainer}>
|
||||||
|
<View style={styles.dividerLine} />
|
||||||
|
<Text style={styles.dividerText}>OR</Text>
|
||||||
|
<View style={styles.dividerLine} />
|
||||||
|
</View>
|
||||||
|
|
||||||
<View style={styles.form}>
|
<View style={styles.form}>
|
||||||
<View style={styles.inputContainer}>
|
<View style={styles.inputContainer}>
|
||||||
<Text style={styles.label}>First Name</Text>
|
<Text style={styles.label}>First Name</Text>
|
||||||
@ -372,4 +381,19 @@ const styles = StyleSheet.create({
|
|||||||
color: "#2563eb",
|
color: "#2563eb",
|
||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
},
|
},
|
||||||
|
dividerContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
dividerLine: {
|
||||||
|
flex: 1,
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: "#ddd",
|
||||||
|
},
|
||||||
|
dividerText: {
|
||||||
|
marginHorizontal: 10,
|
||||||
|
color: "#666",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
64
apps/mobile/src/components/auth/OAuthButtons.tsx
Normal file
64
apps/mobile/src/components/auth/OAuthButtons.tsx
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import React from "react";
|
||||||
|
import * as WebBrowser from "expo-web-browser";
|
||||||
|
import { Button, View, StyleSheet, TouchableOpacity, Text } from "react-native";
|
||||||
|
import { useOAuth } from "@clerk/clerk-expo";
|
||||||
|
import { useWarmUpBrowser } from "../../hooks/useWarmUpBrowser";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
WebBrowser.maybeCompleteAuthSession();
|
||||||
|
|
||||||
|
export function OAuthButtons() {
|
||||||
|
useWarmUpBrowser();
|
||||||
|
|
||||||
|
const { startOAuthFlow } = useOAuth({ strategy: "oauth_google" });
|
||||||
|
|
||||||
|
const onPress = React.useCallback(async () => {
|
||||||
|
try {
|
||||||
|
const { createdSessionId, signIn, signUp, setActive } =
|
||||||
|
await startOAuthFlow();
|
||||||
|
|
||||||
|
if (createdSessionId) {
|
||||||
|
setActive!({ session: createdSessionId });
|
||||||
|
} else {
|
||||||
|
// Use signIn or signUp for next steps such as MFA
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("OAuth error", err);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<TouchableOpacity style={styles.button} onPress={onPress}>
|
||||||
|
<Ionicons name="logo-google" size={20} color="#DB4437" style={styles.icon} />
|
||||||
|
<Text style={styles.text}>Continue with Google</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
width: "100%",
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#ddd",
|
||||||
|
paddingVertical: 12,
|
||||||
|
borderRadius: 8,
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
marginRight: 10,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "500",
|
||||||
|
color: "#333",
|
||||||
|
},
|
||||||
|
});
|
||||||
13
apps/mobile/src/hooks/useWarmUpBrowser.ts
Normal file
13
apps/mobile/src/hooks/useWarmUpBrowser.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import React from "react";
|
||||||
|
import * as WebBrowser from "expo-web-browser";
|
||||||
|
|
||||||
|
export const useWarmUpBrowser = () => {
|
||||||
|
React.useEffect(() => {
|
||||||
|
// Warm up the android browser to improve UX
|
||||||
|
// https://docs.expo.dev/guides/authentication/#improving-user-experience
|
||||||
|
void WebBrowser.warmUpAsync();
|
||||||
|
return () => {
|
||||||
|
void WebBrowser.coolDownAsync();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user