diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 7f50298b9..3d0334942 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -36,7 +36,6 @@ "dependencies": { "@hcaptcha/react-hcaptcha": "1.12.0", "cookie-es": "2.0.0", - "react-google-recaptcha": "3.1.0", "react-google-recaptcha-v3": "1.10.1" }, "devDependencies": { @@ -62,7 +61,6 @@ "@sentry/vite-plugin": "3.3.1", "@types/html-minifier-terser": "7.0.2", "@types/js-yaml": "4.0.9", - "@types/react-google-recaptcha": "2.1.9", "@vitejs/plugin-legacy": "6.1.1", "@vitejs/plugin-react": "4.4.1", "async-es": "3.2.6", diff --git a/apps/ssr/client/modules/login/index.tsx b/apps/ssr/client/modules/login/index.tsx index fa4946e5b..d8a13c297 100644 --- a/apps/ssr/client/modules/login/index.tsx +++ b/apps/ssr/client/modules/login/index.tsx @@ -1,5 +1,5 @@ import { UserAvatar } from "@client/components/ui/user-avatar" -import { loginHandler, oneTimeToken, twoFactor } from "@client/lib/auth" +import { loginHandler, oneTimeToken, signOut, twoFactor } from "@client/lib/auth" import { queryClient } from "@client/lib/query-client" import { useSession } from "@client/query/auth" import { useAuthProviders } from "@client/query/users" @@ -18,39 +18,15 @@ import { Input } from "@follow/components/ui/input/index.js" import { LoadingCircle } from "@follow/components/ui/loading/index.jsx" import { DEEPLINK_SCHEME } from "@follow/shared/constants" import { env } from "@follow/shared/env.ssr" +import HCaptcha from "@hcaptcha/react-hcaptcha" import { zodResolver } from "@hookform/resolvers/zod" import { useCallback, useEffect, useMemo, useRef, useState } from "react" -import ReCAPTCHA from "react-google-recaptcha" import { useForm } from "react-hook-form" import { Trans, useTranslation } from "react-i18next" import { Link, useLocation, useNavigate } from "react-router" import { toast } from "sonner" import { z } from "zod" -function closeRecaptcha( - recaptchaRef: React.RefObject, - resetLoadingState: () => void, -) { - const handleClick = (e: MouseEvent) => { - const recaptchaIframeSelector = - 'iframe[src*="recaptcha/api2"], iframe[src*="www.recaptcha.net"], iframe[src*="google.com/recaptcha"]' - const recaptchaChallengeIframe = document.querySelector(recaptchaIframeSelector) - - if ( - e.target instanceof Element && - recaptchaChallengeIframe && - !recaptchaChallengeIframe.contains(e.target) && - !e.target.closest(".g-recaptcha") - ) { - recaptchaRef.current?.reset() - resetLoadingState() - } - } - - document.addEventListener("click", handleClick) - return () => document.removeEventListener("click", handleClick) -} - export function Login() { const { status, refetch } = useSession() @@ -105,8 +81,19 @@ export function Login() { case isAuthenticated: { return (
-
+
+
+ +

{t("redirect.successMessage", { app_name: APP_NAME })} @@ -237,17 +224,7 @@ function LoginWithPassword() { const [needTwoFactor, setNeedTwoFactor] = useState(false) const [isButtonLoading, setIsButtonLoading] = useState(false) - const recaptchaRef = useRef(null) - - const resetLoadingState = useCallback(() => { - setIsButtonLoading(false) - }, []) - - useEffect(() => { - if (isButtonLoading) { - return closeRecaptcha(recaptchaRef, resetLoadingState) - } - }, [isButtonLoading, resetLoadingState]) + const captchaRef = useRef(null) async function onSubmit(values: z.infer) { setIsButtonLoading(true) @@ -263,8 +240,8 @@ function LoginWithPassword() { return } - const token = await recaptchaRef.current?.executeAsync() - if (!token) { + const response = await captchaRef.current?.execute({ async: true }) + if (!response?.response) { setIsButtonLoading(false) return } @@ -272,7 +249,7 @@ function LoginWithPassword() { const res = await loginHandler("credential", "app", { ...values, headers: { - "x-token": `r2:${token}`, + "x-token": `hc:${response?.response}`, }, }) @@ -350,7 +327,7 @@ function LoginWithPassword() { )} /> )} - +