From 17391daa768fecf97219b4a884808eb1034c3c7a Mon Sep 17 00:00:00 2001 From: leon-morival Date: Fri, 5 Sep 2025 16:52:31 +0200 Subject: [PATCH] login with google --- .gitignore | 1 + android/app/src/main/AndroidManifest.xml | 2 +- app.json | 20 +- package.json | 112 ++--- src/data/keys.js | 18 + src/screens/Login.js | 168 ++++++- yarn.lock | 589 +++++++++++++---------- 7 files changed, 566 insertions(+), 344 deletions(-) diff --git a/.gitignore b/.gitignore index 6d20bd6..6052cac 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ local.properties *.hprof .cxx/ + # node.js # node_modules/ diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 3ff1281..eb377cd 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -29,7 +29,7 @@ - + diff --git a/app.json b/app.json index ebfc1f4..62055b0 100644 --- a/app.json +++ b/app.json @@ -3,8 +3,8 @@ "owner": "minuitagency", "slug": "musicland", "name": "MusicLand", + "scheme": "musicland", "version": "0.0.1", - "scheme": "minuit", "orientation": "portrait", "icon": "./assets/icon.png", "backgroundColor": "#0F0C14", @@ -16,14 +16,7 @@ "fallbackToCacheTimeout": 0 }, "packagerOpts": { - "sourceExts": [ - "js", - "json", - "ts", - "tsx", - "jsx", - "vue" - ] + "sourceExts": ["js", "json", "ts", "tsx", "jsx", "vue"] }, "splash": { "image": "./assets/splash.png", @@ -35,9 +28,7 @@ "supportsTablet": true, "requireFullScreen": true, "userInterfaceStyle": "dark", - "associatedDomains": [ - "applinks:minuit.starter" - ], + "associatedDomains": ["applinks:minuit.starter"], "bundleIdentifier": "com.omedis.musicland", "infoPlist": { "UISupportedInterfaceOrientations": [ @@ -48,10 +39,7 @@ "UIInterfaceOrientationLandscapeLeft", "UIInterfaceOrientationLandscapeRight" ], - "LSApplicationQueriesSchemes": [ - "itms-apps", - "minuit" - ] + "LSApplicationQueriesSchemes": ["itms-apps", "minuit"] }, "config": { "usesNonExemptEncryption": false diff --git a/package.json b/package.json index de9ba6a..e0726f1 100644 --- a/package.json +++ b/package.json @@ -13,29 +13,31 @@ "build:desktop:prod": "yarn build:web && npx pake-cli ./dist/index.html --name minuit --iter-copy-file --icon ./assets/desktopIcon.icns" }, "dependencies": { - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@expo-google-fonts/inter": "^0.4.1", + "@babel/plugin-proposal-export-namespace-from": "~7.18.9", + "@expo-google-fonts/inter": "~0.4.1", "@expo/metro-runtime": "~4.0.1", - "@expo/react-native-action-sheet": "^4.0.1", + "@expo/react-native-action-sheet": "~4.0.1", "@expo/vector-icons": "~14.0.4", - "@gorhom/bottom-sheet": "^4", - "@gorhom/portal": "^1.0.14", - "@legendapp/motion": "^2.2.1", + "@gorhom/bottom-sheet": "~4", + "@gorhom/portal": "~1.0.14", + "@legendapp/motion": "~2.2.1", "@react-native-async-storage/async-storage": "1.23.1", "@react-native-community/datetimepicker": "8.2.0", - "@react-native-community/hooks": "^3.0.0", + "@react-native-community/hooks": "~3.0.0", "@react-native-community/slider": "4.5.5", - "@react-native-masked-view/masked-view": "^0.3.2", - "@react-navigation/bottom-tabs": "^6.0.9", - "@react-navigation/core": "^6.1.0", - "@react-navigation/native": "^6.0.6", - "@react-navigation/stack": "^6.0.11", - "@stripe/react-stripe-js": "^2.5.0", - "@stripe/stripe-js": "^3.0.0", - "add": "^2.0.6", - "deprecated-react-native-prop-types": "^3.0.1", + "@react-native-google-signin/google-signin": "~15.0.0", + "@react-native-masked-view/masked-view": "~0.3.2", + "@react-navigation/bottom-tabs": "~6.0.9", + "@react-navigation/core": "~6.1.0", + "@react-navigation/native": "~6.0.6", + "@react-navigation/stack": "~6.0.11", + "@stripe/react-stripe-js": "~2.5.0", + "@stripe/stripe-js": "~3.0.0", + "add": "~2.0.6", + "deprecated-react-native-prop-types": "~3.0.1", "expo": "~52.0.47", "expo-audio": "~0.3.5", + "expo-auth-session": "~6.0.3", "expo-blur": "~14.0.3", "expo-build-properties": "~0.13.3", "expo-camera": "~16.0.18", @@ -56,63 +58,63 @@ "expo-status-bar": "~2.0.1", "expo-system-ui": "~4.0.9", "expo-video": "~2.0.6", - "firebase": "^9.20.0", - "lodash": "^4.17.21", - "moment": "^2.29.4", - "numbro": "^2.3.6", + "expo-web-browser": "~14.0.2", + "firebase": "~9.20.0", + "lodash": "~4.17.21", + "moment": "~2.29.4", + "numbro": "~2.3.6", "react": "18.3.1", "react-dom": "18.3.1", "react-native": "0.76.9", - "react-native-actions-sheet": "^0.9.7", - "react-native-compressor": "^1.12.0", - "react-native-country-picker-modal": "^2.0.0", - "react-native-dialog": "^9.3.0", - "react-native-figma-squircle": "^0.3.4", + "react-native-actions-sheet": "~0.9.7", + "react-native-compressor": "~1.12.0", + "react-native-country-picker-modal": "~2.0.0", + "react-native-dialog": "~9.3.0", + "react-native-figma-squircle": "~0.3.4", "react-native-gesture-handler": "~2.20.2", - "react-native-hyperlink": "^0.0.22", - "react-native-keyboard-aware-scroll-view": "^0.9.5", - "react-native-linear-gradient": "^2.8.3", - "react-native-minuit": "^1.3.52", - "react-native-popup-menu": "^0.18.0", + "react-native-hyperlink": "~0.0.22", + "react-native-keyboard-aware-scroll-view": "~0.9.5", + "react-native-linear-gradient": "~2.8.3", + "react-native-minuit": "~1.3.52", + "react-native-popup-menu": "~0.18.0", "react-native-reanimated": "~3.16.1", - "react-native-reanimated-carousel": "^4.0.3", - "react-native-responsive-dimensions": "^3.1.1", + "react-native-reanimated-carousel": "~4.0.3", + "react-native-responsive-dimensions": "~3.1.1", "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", - "react-native-sortables": "^1.8.0", - "react-native-store-review": "^0.3.0", - "react-native-super-grid": "^5.0.0", + "react-native-sortables": "~1.8.0", + "react-native-store-review": "~0.3.0", + "react-native-super-grid": "~5.0.0", "react-native-svg": "15.8.0", - "react-native-swiper-flatlist": "^3.2.5", + "react-native-swiper-flatlist": "~3.2.5", "react-native-web": "~0.19.6", - "react-native-web-linear-gradient": "^1.1.2", + "react-native-web-linear-gradient": "~1.1.2", "react-native-webview": "13.12.5", - "reactn": "^2.2.7", - "rxjs": "^7.6.0" + "reactn": "~2.2.7", + "rxjs": "~7.6.0" }, "devDependencies": { - "@babel/core": "^7.20.5", - "@babel/parser": "^7.25.6", - "@babel/traverse": "^7.25.6", + "@babel/core": "^7.25.2", + "@babel/parser": "~7.25.6", + "@babel/traverse": "~7.25.6", "@types/react": "~18.3.12", - "eslint": "^8.57.0", + "eslint": "~8.57.0", "eslint-config-expo": "~8.0.1", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.3", - "imagemin": "^9.0.0", - "imagemin-gifsicle": "^7.0.0", - "imagemin-jpegtran": "^7.0.0", - "imagemin-optipng": "^8.0.0", - "imagemin-svgo": "^11.0.1", - "prettier": "^3.2.5", - "typescript": "^5.3.3" + "eslint-config-prettier": "~9.1.0", + "eslint-plugin-prettier": "~5.1.3", + "imagemin": "~9.0.0", + "imagemin-gifsicle": "~7.0.0", + "imagemin-jpegtran": "~7.0.0", + "imagemin-optipng": "~8.0.0", + "imagemin-svgo": "~11.0.1", + "prettier": "~3.2.5", + "typescript": "~5.3.3" }, "resolutions": { - "firebase": "^9.20.0", + "firebase": "~9.20.0", "react-error-overlay": "6.0.9" }, - "private": true - , + "private": true, "expo": { "doctor": { "reactNativeDirectoryCheck": { diff --git a/src/data/keys.js b/src/data/keys.js index 9612e2f..5a3d833 100644 --- a/src/data/keys.js +++ b/src/data/keys.js @@ -1,3 +1,21 @@ export const STRIPE_PUBLISHABLE_KEY_TEST = ".."; export const STRIPE_PUBLISHABLE_KEY_LIVE = "..."; export const GOOGLE_API_KEY = "..."; + +// OAuth Client IDs for Google Sign-In +// Use platform-specific client IDs from your Google Cloud Console / Firebase settings +// - Android: client_type 1 from config/google-services.json (package + SHA-1 bound) +// - iOS: CLIENT_ID from config/GoogleService-Info.plist +// - Web/Expo Go: Web client (client_type 3) + +// Web client ID (client_type 3) +export const GOOGLE_WEB_CLIENT_ID = + "305598753437-dtjknrpfrjt3bdd7838nga41m5i4emva.apps.googleusercontent.com"; + +// iOS client ID (may need updating to match the iOS bundle for this project) +export const GOOGLE_IOS_CLIENT_ID = + "943006074419-h43c7p48nhn5f4td4oimv4dq7b1p3s29.apps.googleusercontent.com"; + +// Android client ID (client_type 1 from google-services.json) +export const GOOGLE_ANDROID_CLIENT_ID = + "305598753437-qck73beo37mi04qlautgafbpdl3ccaoh.apps.googleusercontent.com"; diff --git a/src/screens/Login.js b/src/screens/Login.js index d1df316..347b9c3 100644 --- a/src/screens/Login.js +++ b/src/screens/Login.js @@ -1,36 +1,64 @@ -import React, { useState } from "react"; +/* eslint-disable react/display-name */ +import * as AuthSession from "expo-auth-session"; +import * as GoogleAuth from "expo-auth-session/providers/google"; +import * as WebBrowser from "expo-web-browser"; +import React, { useEffect, useState } from "react"; +import { Platform, Pressable, Text, View } from "react-native"; import { useGlobal } from "reactn"; -import { Pressable, Text, View } from "react-native"; -import Page from "../layouts/Page.js"; import { background } from "../assets"; -import { Input } from "../components/Input.js"; import GradientButton from "../components/GradientButton.js"; -import Palette from "../styles/Palette.js"; -import { FONT_FAMILY } from "../styles/Fonts.js"; -import { navigate } from "../navigation/NavigationService.js"; -import { Routes } from "../navigation"; +import { Input } from "../components/Input.js"; import ItemContainer from "../components/ItemContainer/ItemContainer.js"; import firebase, { usersRef } from "../config/firebase"; +import { + GOOGLE_ANDROID_CLIENT_ID, + GOOGLE_IOS_CLIENT_ID, + GOOGLE_WEB_CLIENT_ID, +} from "../data/keys"; +import { isWeb } from "../hooks/useLayoutType"; +import Page from "../layouts/Page.js"; +import { Routes } from "../navigation"; +import { navigate } from "../navigation/NavigationService.js"; +import { FONT_FAMILY } from "../styles/Fonts.js"; +import Palette from "../styles/Palette.js"; export default ({ navigation }) => { + WebBrowser.maybeCompleteAuthSession(); const [, setTooltip] = useGlobal("_tooltip"); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [loading, setLoading] = useState(false); + // Let the provider compute a compliant redirect URI for native (com.googleusercontent.apps.:/oauth2redirect) + // Avoid forcing a custom scheme like musicland:// which Google can reject for native apps. + + const [request, response, promptAsync] = GoogleAuth.useAuthRequest({ + iosClientId: GOOGLE_IOS_CLIENT_ID, + androidClientId: GOOGLE_ANDROID_CLIENT_ID, + webClientId: GOOGLE_WEB_CLIENT_ID, + expoClientId: GOOGLE_WEB_CLIENT_ID, + // Use Authorization Code + PKCE to comply with Google OAuth for native apps + responseType: AuthSession.ResponseType.Code, + usePKCE: true, + scopes: ["openid", "profile", "email"], + }); + + const afterLoginNavigate = async () => { + const uid = firebase.auth().currentUser?.uid; + if (!uid) throw new Error("Aucun utilisateur après connexion"); + const snap = await usersRef.doc(uid).get(); + const hasUserName = !!snap.data()?.userName; + if (hasUserName) { + navigation.reset({ index: 0, routes: [{ name: Routes.BottomTab }] }); + } else { + navigation.reset({ index: 0, routes: [{ name: Routes.CreatePseudo }] }); + } + }; const onLogin = async () => { try { setLoading(true); await firebase.auth().signInWithEmailAndPassword(email.trim(), password); - const uid = firebase.auth().currentUser?.uid; - if (!uid) throw new Error("Aucun utilisateur après connexion"); - const snap = await usersRef.doc(uid).get(); - const hasUserName = !!snap.data()?.userName; - if (hasUserName) { - navigation.reset({ index: 0, routes: [{ name: Routes.BottomTab }] }); - } else { - navigation.reset({ index: 0, routes: [{ name: Routes.CreatePseudo }] }); - } + await afterLoginNavigate(); } catch (e) { console.log("Login error", e?.message); setTooltip({ text: e?.message || "Connexion impossible", type: "error" }); @@ -39,6 +67,98 @@ export default ({ navigation }) => { } }; + const onLoginWithGoogle = async () => { + try { + setLoading(true); + if (isWeb) { + const provider = new firebase.auth.GoogleAuthProvider(); + provider.addScope("profile"); + provider.addScope("email"); + await firebase.auth().signInWithPopup(provider); + await afterLoginNavigate(); + setLoading(false); + } else { + // Use defaults from the request; don't override with proxy here + const result = await promptAsync(); + if (result?.type !== "success") { + // Cancelled or errored during the browser flow + setLoading(false); + } + } + } catch (e) { + console.log("Google Login error", e?.message); + setTooltip({ + text: e?.message || "Connexion Google impossible. Merci de réessayer.", + type: "error", + }); + setLoading(false); + } + }; + + // Handle native Google OAuth response + useEffect(() => { + const handleNativeGoogleResponse = async () => { + try { + if (response?.type === "success") { + // If using Expo proxy, tokens can be present already. + let idToken = + response?.authentication?.idToken || response?.params?.id_token; + + if (!idToken) { + // Otherwise, exchange the authorization code for tokens using PKCE. + const code = response?.params?.code || response?.authentication?.code; + if (!code) throw new Error("Code d'autorisation Google manquant"); + + // Use the exact clientId used during the authorize request. + const clientId = request?.clientId; + const discovery = { + authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth", + tokenEndpoint: "https://oauth2.googleapis.com/token", + revocationEndpoint: "https://oauth2.googleapis.com/revoke", + }; + + // Light debug: helps identify redirect/client mismatches in dev. + console.log("Google token exchange", { + clientId, + redirectUri: request?.redirectUri, + hasCodeVerifier: !!request?.codeVerifier, + }); + + const tokenResponse = await AuthSession.exchangeCodeAsync( + { + clientId, + code, + redirectUri: request?.redirectUri, + extraParams: { code_verifier: request?.codeVerifier }, + }, + discovery + ); + idToken = tokenResponse?.id_token; + } + + if (!idToken) throw new Error("Jeton Google manquant (échange/retour)"); + + const credential = firebase.auth.GoogleAuthProvider.credential(idToken); + await firebase.auth().signInWithCredential(credential); + await afterLoginNavigate(); + } + } catch (e) { + console.log("Google native sign-in error", e?.message); + setTooltip({ + text: e?.message || "Connexion Google impossible", + type: "error", + }); + } finally { + setLoading(false); + } + }; + + if (!isWeb && response) { + handleNativeGoogleResponse(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [response]); + return ( { setValue={setPassword} isBlur /> - navigate(Routes.ForgotPassword)} - > + navigate(Routes.ForgotPassword)}> { onPress={onLogin} disabled={loading || !email || !password} /> + + =2.0.0: resolved "https://registry.yarnpkg.com/react-native-haptic-feedback/-/react-native-haptic-feedback-2.3.3.tgz#88b6876e91399a69bd1b551fe1681b2f3dc1214e" integrity sha512-svS4D5PxfNv8o68m9ahWfwje5NqukM3qLS48+WTdhbDkNUkOhP9rDfDSRHzlhk4zq+ISjyw95EhLeh8NkKX5vQ== -react-native-hyperlink@^0.0.22: +react-native-hyperlink@~0.0.22: version "0.0.22" resolved "https://registry.yarnpkg.com/react-native-hyperlink/-/react-native-hyperlink-0.0.22.tgz#9f553390b5f96ae473d942639c40bce6579abc89" integrity sha512-IVhG+aP2bAnllUEr08/+rGA3cbpzyl83PtOfe94higfWUR8E7rUGThj21tdhx8SWAyl+4XO1K864tA6ybVbMFA== @@ -8722,7 +8799,7 @@ react-native-iphone-x-helper@^1.0.3: resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz#20c603e9a0e765fd6f97396638bdeb0e5a60b010" integrity sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg== -react-native-keyboard-aware-scroll-view@^0.9.5: +react-native-keyboard-aware-scroll-view@~0.9.5: version "0.9.5" resolved "https://registry.yarnpkg.com/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.9.5.tgz#e2e9665d320c188e6b1f22f151b94eb358bf9b71" integrity sha512-XwfRn+T/qBH9WjTWIBiJD2hPWg0yJvtaEw6RtPCa5/PYHabzBaWxYBOl0usXN/368BL1XktnZPh8C2lmTpOREA== @@ -8730,12 +8807,12 @@ react-native-keyboard-aware-scroll-view@^0.9.5: prop-types "^15.6.2" react-native-iphone-x-helper "^1.0.3" -react-native-linear-gradient@^2.8.3: +react-native-linear-gradient@~2.8.3: version "2.8.3" resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz#9a116649f86d74747304ee13db325e20b21e564f" integrity sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA== -react-native-minuit@^1.3.52: +react-native-minuit@~1.3.52: version "1.3.74" resolved "https://registry.yarnpkg.com/react-native-minuit/-/react-native-minuit-1.3.74.tgz#65e8ba3e5609f8c8fe08d6dd6168003291453891" integrity sha512-2BoqH2c3G9OGS4frtYKV9r+7QLfwAkbfJsZKGlZKrQvQLKcEkz0cIPX4noAJYL/+b34jBjs3QxbDo2AoMcRUYg== @@ -8760,12 +8837,12 @@ react-native-modalbox@^2.0.2: dependencies: prop-types "^15.5.10" -react-native-popup-menu@^0.18.0: +react-native-popup-menu@~0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/react-native-popup-menu/-/react-native-popup-menu-0.18.0.tgz#723c4df6b790ee3cc92ae698e7e5844ee1a170f9" integrity sha512-XD3gyp/hwL5YWw2J034DerfvbJ6S2YHqAzvqAFRU+UGnFD4JyTqggfm4UyynBD26O1PDoRb45Loil+NZCGfCnA== -react-native-reanimated-carousel@^4.0.3: +react-native-reanimated-carousel@~4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/react-native-reanimated-carousel/-/react-native-reanimated-carousel-4.0.3.tgz#975f4ff3f5da5bb3790fe60850a46ad8119612bc" integrity sha512-YZXlvZNghR5shFcI9hTA7h7bEhh97pfUSLZvLBAshpbkuYwJDKmQXejO/199T6hqGq0wCRwR0CWf2P4Vs6A4Fw== @@ -8787,7 +8864,7 @@ react-native-reanimated@~3.16.1: convert-source-map "^2.0.0" invariant "^2.2.4" -react-native-responsive-dimensions@^3.1.1: +react-native-responsive-dimensions@^3.1.1, react-native-responsive-dimensions@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/react-native-responsive-dimensions/-/react-native-responsive-dimensions-3.1.1.tgz#c4daf977b30a909f21164de53a8ba4c9451efefc" integrity sha512-Vo2OhWsphq0HgKsmeZOeyW+c+vsFn1ZaCFkGDgdeCEEiLriT76jGA1JlUjtrj27hvyo/xzeTlBZ+vBso1A84fw== @@ -8810,24 +8887,24 @@ react-native-screens@~4.4.0: react-freeze "^1.0.0" warn-once "^0.1.0" -react-native-sortables@^1.8.0: +react-native-sortables@~1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/react-native-sortables/-/react-native-sortables-1.8.0.tgz#fabdc8a757eb1e847eda3b4af1f9d349780a1079" integrity sha512-uoNY0uiHikq3eKJoF85CATMPpo9jS7t37XUlunxSGjjbGi4L05os8eJBGNZSR+3NQgK2FtYGGkQtFbeSJIwmDg== optionalDependencies: react-native-haptic-feedback ">=2.0.0" -react-native-store-review@^0.3.0: +react-native-store-review@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/react-native-store-review/-/react-native-store-review-0.3.0.tgz#67480b9736c10bd00ad8d4d80324d2146e18d7dd" integrity sha512-PipH/p3O10DDCUWHiW0sVZ0020HPx6gRFFZOyuAYRRVwdssO7or/+H2pHTlwUt2lasVzLenTf2aZ9sMrpryuKA== -react-native-super-grid@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/react-native-super-grid/-/react-native-super-grid-5.1.0.tgz#2b263232b967045846685ed456619798d7ae7999" - integrity sha512-pKzkjdc9pgrAIEJDr5k4HH5i9RSmUZ3mw21QEcZr2ECulg2HYrUV5FAdi8NMOmBeenXY4NNP3zVLckHBd2rBqA== +react-native-super-grid@~5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/react-native-super-grid/-/react-native-super-grid-5.0.1.tgz#c688553430e94e904d82b8c8948116d3f0a416fb" + integrity sha512-BNkLgQT79zv906TAVWGl+7B+5g6eL0GDTtO6te/g/WYOkxM8OXXJN8/Q1aIUBOpDo1L0Wv0BDR6EGHuhndmcRw== dependencies: - prop-types "^15.6.2" + prop-types "^15.6.0" react-native-svg@15.8.0: version "15.8.0" @@ -8843,12 +8920,12 @@ react-native-swipe-gestures@^1.0.5: resolved "https://registry.yarnpkg.com/react-native-swipe-gestures/-/react-native-swipe-gestures-1.0.5.tgz#a172cb0f3e7478ccd681fd36b8bfbcdd098bde7c" integrity sha512-Ns7Bn9H/Tyw278+5SQx9oAblDZ7JixyzeOczcBK8dipQk2pD7Djkcfnf1nB/8RErAmMLL9iXgW0QHqiII8AhKw== -react-native-swiper-flatlist@^3.2.5: +react-native-swiper-flatlist@~3.2.5: version "3.2.5" resolved "https://registry.yarnpkg.com/react-native-swiper-flatlist/-/react-native-swiper-flatlist-3.2.5.tgz#d69030e2986b8a322ff274ad2896ca809c1ebe0e" integrity sha512-pP6Yioo//PgxBf1Ac/utPaAMaCTXF0QW/Q55hQofGtE7B5/hL0nb9u4cXEdgGJslx0oBCkir4AJAbbD5FpWnaA== -react-native-web-linear-gradient@^1.1.2: +react-native-web-linear-gradient@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/react-native-web-linear-gradient/-/react-native-web-linear-gradient-1.1.2.tgz#33f85f7085a0bb5ffa5106faf02ed105b92a9ed7" integrity sha512-SmUnpwT49CEe78pXvIvYf72Es8Pv+ZYKCnEOgb2zAKpEUDMo0+xElfRJhwt5nfI8krJ5WbFPKnoDgD0uUjAN1A== @@ -8931,7 +9008,7 @@ react@18.3.1: dependencies: loose-envify "^1.1.0" -reactn@^2.2.7: +reactn@^2.2.7, reactn@~2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/reactn/-/reactn-2.2.7.tgz#4d9a94ab0d8a540062666408e4bf1fae6892cecc" integrity sha512-cqnt23kWN/ABqEZhW3OlpqI1DgTaaNDeHpSHtyd81qk0H1jd32zPTzJ69Hpzti2WakwNYveGFPIgI6i7E7nXOA== @@ -9206,13 +9283,20 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.5.7, rxjs@^7.6.0: +rxjs@^7.5.7: version "7.8.2" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== dependencies: tslib "^2.1.0" +rxjs@~7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.6.0.tgz#361da5362b6ddaa691a2de0b4f2d32028f1eb5a2" + integrity sha512-DDa7d8TFNUalGC9VqXvQ1euWNN7sc63TrUCuM9J998+ViviahMIjKSOU7rfcgFOF+FCD71BhDRv4hrFz+ImDLQ== + dependencies: + tslib "^2.1.0" + safe-array-concat@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" @@ -9958,12 +10042,13 @@ svgo@^3.3.2: csso "^5.0.5" picocolors "^1.0.0" -synckit@^0.11.7: - version "0.11.11" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.11.tgz#c0b619cf258a97faa209155d9cd1699b5c998cb0" - integrity sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw== +synckit@^0.8.6: + version "0.8.8" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" + integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== dependencies: - "@pkgr/core" "^0.2.9" + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" tar-stream@^1.5.2: version "1.6.2" @@ -10179,7 +10264,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0: +tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -10278,10 +10363,10 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" -typescript@^5.3.3: - version "5.9.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6" - integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A== +typescript@~5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== ua-parser-js@^0.7.33: version "0.7.41"