Add spinner during captcha verification

Show a loading spinner and message while captcha is being verified. Imported Spinner and added an optional captchaVerifying prop to PasswordLogin to toggle between the TencentCaptchaModal and a waiting state. In qq_login.tsx introduced captchaVerifying state, set it true before the captcha login request and reset it in finally, and passed the prop down to the PasswordLogin component.
This commit is contained in:
手瓜一十雪
2026-02-21 13:39:35 +08:00
parent f9764c9559
commit 964fd98914
2 changed files with 26 additions and 9 deletions

View File

@@ -6,6 +6,7 @@ import { Input } from '@heroui/input';
import { useState } from 'react'; import { useState } from 'react';
import { toast } from 'react-hot-toast'; import { toast } from 'react-hot-toast';
import { IoChevronDown } from 'react-icons/io5'; import { IoChevronDown } from 'react-icons/io5';
import { Spinner } from '@heroui/spinner';
import type { QQItem } from '@/components/quick_login'; import type { QQItem } from '@/components/quick_login';
import { isQQQuickNewItem } from '@/utils/qq'; import { isQQQuickNewItem } from '@/utils/qq';
@@ -25,6 +26,7 @@ interface PasswordLoginProps {
uin: string; uin: string;
password: string; password: string;
} | null; } | null;
captchaVerifying?: boolean;
newDeviceState?: { newDeviceState?: {
needNewDevice: boolean; needNewDevice: boolean;
jumpUrl: string; jumpUrl: string;
@@ -34,7 +36,7 @@ interface PasswordLoginProps {
onNewDeviceCancel?: () => void; onNewDeviceCancel?: () => void;
} }
const PasswordLogin: React.FC<PasswordLoginProps> = ({ onSubmit, onCaptchaSubmit, onNewDeviceVerified, isLoading, qqList, captchaState, newDeviceState, onCaptchaCancel, onNewDeviceCancel }) => { const PasswordLogin: React.FC<PasswordLoginProps> = ({ onSubmit, onCaptchaSubmit, onNewDeviceVerified, isLoading, qqList, captchaState, captchaVerifying, newDeviceState, onCaptchaCancel, onNewDeviceCancel }) => {
const [uin, setUin] = useState(''); const [uin, setUin] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
@@ -54,14 +56,25 @@ const PasswordLogin: React.FC<PasswordLoginProps> = ({ onSubmit, onCaptchaSubmit
<div className='flex flex-col gap-8'> <div className='flex flex-col gap-8'>
{captchaState?.needCaptcha && captchaState.proofWaterUrl ? ( {captchaState?.needCaptcha && captchaState.proofWaterUrl ? (
<div className='flex flex-col gap-4 items-center'> <div className='flex flex-col gap-4 items-center'>
<p className='text-warning text-sm'></p> {captchaVerifying ? (
<TencentCaptchaModal <>
proofWaterUrl={captchaState.proofWaterUrl} <p className='text-primary text-sm'>...</p>
onSuccess={(data) => { <div className='flex items-center justify-center py-8 gap-3'>
onCaptchaSubmit?.(captchaState.uin, captchaState.password, data); <Spinner size='lg' />
}} </div>
onCancel={onCaptchaCancel} </>
/> ) : (
<>
<p className='text-warning text-sm'></p>
<TencentCaptchaModal
proofWaterUrl={captchaState.proofWaterUrl}
onSuccess={(data) => {
onCaptchaSubmit?.(captchaState.uin, captchaState.password, data);
}}
onCancel={onCaptchaCancel}
/>
</>
)}
<Button <Button
variant='light' variant='light'
color='danger' color='danger'

View File

@@ -65,6 +65,7 @@ export default function QQLoginPage () {
uin: string; uin: string;
password: string; password: string;
} | null>(null); } | null>(null);
const [captchaVerifying, setCaptchaVerifying] = useState(false);
const [newDeviceState, setNewDeviceState] = useState<{ const [newDeviceState, setNewDeviceState] = useState<{
needNewDevice: boolean; needNewDevice: boolean;
jumpUrl: string; jumpUrl: string;
@@ -130,6 +131,7 @@ export default function QQLoginPage () {
const onCaptchaSubmit = async (uin: string, password: string, captchaData: CaptchaCallbackData) => { const onCaptchaSubmit = async (uin: string, password: string, captchaData: CaptchaCallbackData) => {
setIsLoading(true); setIsLoading(true);
setCaptchaVerifying(true);
try { try {
const passwordMd5 = CryptoJS.MD5(password).toString(); const passwordMd5 = CryptoJS.MD5(password).toString();
const result = await QQManager.captchaLogin(uin, passwordMd5, captchaData.ticket, captchaData.randstr, captchaData.sid); const result = await QQManager.captchaLogin(uin, passwordMd5, captchaData.ticket, captchaData.randstr, captchaData.sid);
@@ -153,6 +155,7 @@ export default function QQLoginPage () {
setCaptchaState(null); setCaptchaState(null);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
setCaptchaVerifying(false);
} }
}; };
@@ -355,6 +358,7 @@ export default function QQLoginPage () {
onNewDeviceVerified={onNewDeviceVerified} onNewDeviceVerified={onNewDeviceVerified}
qqList={qqList} qqList={qqList}
captchaState={captchaState} captchaState={captchaState}
captchaVerifying={captchaVerifying}
newDeviceState={newDeviceState} newDeviceState={newDeviceState}
onCaptchaCancel={onCaptchaCancel} onCaptchaCancel={onCaptchaCancel}
onNewDeviceCancel={onNewDeviceCancel} onNewDeviceCancel={onNewDeviceCancel}