diff --git a/.gitignore b/.gitignore
index 27a6f5d..7aadb01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,4 +44,8 @@ app-example
# Continuous Native Generation
android/
-ios/
\ No newline at end of file
+ios/
+
+# Google Auth
+google-services.json
+GoogleService-Info.plist
\ No newline at end of file
diff --git a/GoogleService-Info.plist b/GoogleService-Info.plist
new file mode 100644
index 0000000..f88603e
--- /dev/null
+++ b/GoogleService-Info.plist
@@ -0,0 +1,14 @@
+
+
+
+
+ CLIENT_ID
+ 742231570327-s21pt82lc97lc35obefgn5nrdq4m0rn6.apps.googleusercontent.com
+ REVERSED_CLIENT_ID
+ com.googleusercontent.apps.742231570327-s21pt82lc97lc35obefgn5nrdq4m0rn6
+ PLIST_VERSION
+ 1
+ BUNDLE_ID
+ pt.findit.clientapp
+
+
\ No newline at end of file
diff --git a/app.json b/app.json
index fe9ac54..44b2937 100644
--- a/app.json
+++ b/app.json
@@ -15,7 +15,8 @@
"dark": "./assets/images/logos/ios-dark.png",
"light": "./assets/images/logos/ios-light.png",
"tinted": "./assets/images/logos/ios-tinted.png"
- }
+ },
+ "googleServicesFile": "./GoogleService-Info.plist"
},
"android": {
"adaptiveIcon": {
@@ -53,6 +54,13 @@
{
"locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location."
}
+ ],
+ "@maplibre/maplibre-react-native",
+ [
+ "@react-native-google-signin/google-signin",
+ {
+ "iosUrlScheme": "com.googleusercontent.apps.742231570327-s21pt82lc97lc35obefgn5nrdq4m0rn6"
+ }
]
],
"experiments": {
@@ -74,4 +82,4 @@
"url": "https://u.expo.dev/0bab4576-b4ae-4290-9835-f6e61e1b2bf8"
}
}
-}
\ No newline at end of file
+}
diff --git a/bun.lock b/bun.lock
index 9ed39c3..f9f818c 100644
--- a/bun.lock
+++ b/bun.lock
@@ -15,6 +15,7 @@
"@graphql-typed-document-node/core": "~3.2.0",
"@legendapp/list": "^1.0.10",
"@maplibre/maplibre-react-native": "~10.1.4",
+ "@react-native-google-signin/google-signin": "^14.0.1",
"@react-native-masked-view/masked-view": "~0.3.2",
"@react-native-picker/picker": "^2.11.0",
"@react-navigation/bottom-tabs": "~7.2.0",
@@ -681,6 +682,8 @@
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw=="],
+ "@react-native-google-signin/google-signin": ["@react-native-google-signin/google-signin@14.0.1", "", { "peerDependencies": { "expo": ">=52.0.40", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["expo", "react-dom"] }, "sha512-2f903eaHiv/Ob96vsWZitz+Z0k2J2W0/C7Ygrr6ejAT2JVzJCatmjF/eq62MWhuTNdU2WDX/oePxMbpQW6k2UA=="],
+
"@react-native-masked-view/masked-view": ["@react-native-masked-view/masked-view@0.3.2", "", { "peerDependencies": { "react": ">=16", "react-native": ">=0.57" } }, "sha512-XwuQoW7/GEgWRMovOQtX3A4PrXhyaZm0lVUiY8qJDvdngjLms9Cpdck6SmGAUNqQwcj2EadHC1HwL0bEyoa/SQ=="],
"@react-native-picker/picker": ["@react-native-picker/picker@2.11.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-QuZU6gbxmOID5zZgd/H90NgBnbJ3VV6qVzp6c7/dDrmWdX8S0X5YFYgDcQFjE3dRen9wB9FWnj2VVdPU64adSg=="],
diff --git a/components/LoginBottomSheet.tsx b/components/LoginBottomSheet.tsx
index 7b98628..057232a 100644
--- a/components/LoginBottomSheet.tsx
+++ b/components/LoginBottomSheet.tsx
@@ -1,21 +1,20 @@
import { GradientPill } from "@/components/GradientPill";
import Background from "@/components/Background";
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
-import { Platform, View } from "react-native";
+import { View } from "react-native";
import { ThemedText } from "@/components/ThemedText";
import { Button } from "@/components/Button";
-import AppleIcon from "@/assets/images/brands/apple.svg";
import GoogleIcon from "@/assets/images/brands/google.svg";
-import React, { useRef } from "react";
+import React, { useEffect, useRef } from "react";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useBackground } from "@/hooks/useBackground";
import { Redirect, useRouter } from "expo-router";
import { SharedValue } from "react-native-reanimated";
import { gql } from "@/graphql";
-import { FetchResult, useMutation } from "@apollo/client";
-import { UpsertUserMutation } from "@/graphql/graphql";
+import { useMutation } from "@apollo/client";
import { useToast } from "@/hooks/useToast";
import { useAuth } from "@/hooks/useAuth";
+import { GoogleSignin } from "@react-native-google-signin/google-signin";
interface LoginBottomSheetProps {
animatedPosition: SharedValue;
@@ -24,7 +23,7 @@ interface LoginBottomSheetProps {
interface LoginMethod {
name: string;
icon: React.ComponentProps["Icon"];
- onPress: () => Promise>;
+ onPress: () => Promise;
type: "primary" | "secondary";
}
@@ -46,16 +45,11 @@ export const LoginBottomSheet = ({
const { id, setId } = useAuth();
const { toast, toastOnError } = useToast();
+ useEffect(() => {
+ GoogleSignin.configure({});
+ }, []);
+
const [upsertUser, { loading }] = useMutation(UPSERT_USER, {
- variables: {
- // Temporary user data
- model: {
- birth_date: "2003-11-08",
- email: "matilde@findit-app.pt",
- first_name: "Matilde",
- last_name: "Silva",
- },
- },
onCompleted: async (data) => {
if (!data.upsertUser) {
toast({
@@ -71,22 +65,40 @@ export const LoginBottomSheet = ({
onError: toastOnError,
});
+ const signIn = async () => {
+ try {
+ const signInResponse = await GoogleSignin.signIn();
+ const userInfo = signInResponse.data?.user;
+ if (signInResponse.type === "success") {
+ await upsertUser({
+ variables: {
+ model: {
+ email: userInfo?.email ?? "",
+ first_name: userInfo?.givenName ?? "",
+ last_name: userInfo?.familyName ?? "",
+ birth_date: "",
+ },
+ },
+ });
+ } else if (signInResponse.type === "cancelled" || !userInfo) {
+ toast({ title: "Sign in cancelled", text: "Please try again." });
+ return;
+ }
+ } catch (error) {
+ toast({ title: "Error signing in", text: error as string });
+ }
+ };
+
if (id) {
return ;
}
const methods: LoginMethod[] = [
- {
- name: "Apple",
- icon: AppleIcon,
- onPress: async () => await upsertUser(),
- type: Platform.OS === "ios" ? "primary" : "secondary",
- },
{
name: "Google",
icon: GoogleIcon,
- onPress: async () => await upsertUser(),
- type: Platform.OS === "android" ? "primary" : "secondary",
+ onPress: async () => await signIn(),
+ type: "primary",
},
];
@@ -108,12 +120,7 @@ export const LoginBottomSheet = ({
by logging in.
-
+
{methods.map((method) => (