social login

implemented, we can add more providers later
This commit is contained in:
echo 2025-11-20 19:28:39 +01:00
parent 8b4cef33dc
commit a96f1902c5
5 changed files with 142 additions and 17 deletions

Binary file not shown.

View File

@ -1,4 +1,4 @@
import React from "react";
import { useState, useEffect } from "react";
import { useSignIn, useAuth } from "@clerk/clerk-expo";
import { useRouter } from "expo-router";
import {
@ -12,19 +12,20 @@ import {
Platform,
ScrollView,
} from "react-native";
import { OAuthButtons } from "../../components/auth/OAuthButtons";
export default function SignInScreen() {
const { signIn, setActive, isLoaded } = useSignIn();
const { isSignedIn } = useAuth();
const router = useRouter();
const [emailAddress, setEmailAddress] = React.useState("");
const [password, setPassword] = React.useState("");
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState("");
const [emailAddress, setEmailAddress] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
// Redirect if already signed in
React.useEffect(() => {
useEffect(() => {
if (isSignedIn) {
router.replace("/(tabs)");
}
@ -100,6 +101,14 @@ export default function SignInScreen() {
</View>
) : 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.inputContainer}>
<Text style={styles.label}>Email</Text>
@ -256,4 +265,19 @@ const styles = StyleSheet.create({
color: "#2563eb",
fontWeight: "600",
},
dividerContainer: {
flexDirection: "row",
alignItems: "center",
marginBottom: 24,
},
dividerLine: {
flex: 1,
height: 1,
backgroundColor: "#ddd",
},
dividerText: {
marginHorizontal: 10,
color: "#666",
fontSize: 14,
},
});

View File

@ -1,4 +1,4 @@
import React from "react";
import { useState, useEffect } from "react";
import { useSignUp, useAuth } from "@clerk/clerk-expo";
import { useRouter } from "expo-router";
import {
@ -12,23 +12,24 @@ import {
Platform,
ScrollView,
} from "react-native";
import { OAuthButtons } from "../../components/auth/OAuthButtons";
export default function SignUpScreen() {
const { signUp, setActive, isLoaded } = useSignUp();
const { isSignedIn } = useAuth();
const router = useRouter();
const [emailAddress, setEmailAddress] = React.useState("");
const [password, setPassword] = React.useState("");
const [firstName, setFirstName] = React.useState("");
const [lastName, setLastName] = React.useState("");
const [pendingVerification, setPendingVerification] = React.useState(false);
const [code, setCode] = React.useState("");
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState("");
const [emailAddress, setEmailAddress] = useState("");
const [password, setPassword] = useState("");
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [pendingVerification, setPendingVerification] = useState(false);
const [code, setCode] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
// Redirect if already signed in
React.useEffect(() => {
useEffect(() => {
if (isSignedIn) {
router.replace("/(tabs)");
}
@ -182,6 +183,14 @@ export default function SignUpScreen() {
</View>
) : 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.inputContainer}>
<Text style={styles.label}>First Name</Text>
@ -372,4 +381,19 @@ const styles = StyleSheet.create({
color: "#2563eb",
fontWeight: "600",
},
dividerContainer: {
flexDirection: "row",
alignItems: "center",
marginBottom: 24,
},
dividerLine: {
flex: 1,
height: 1,
backgroundColor: "#ddd",
},
dividerText: {
marginHorizontal: 10,
color: "#666",
fontSize: 14,
},
});

View 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",
},
});

View 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();
};
}, []);
};