fix: upgrade ALTCHA widget to v2.3.0 and rewrite component
- Upgrade from v0.5.0 to v2.3.0 (latest) - Use dangerouslySetInnerHTML for proper web component rendering - Add MutationObserver for reliable event binding - Enable debug mode on widget to diagnose issues - Simplify component API with onVerified/onError callbacks
This commit is contained in:
parent
96c0348d3a
commit
9f1dd857c4
|
|
@ -17,14 +17,14 @@ export default function LoginPage() {
|
|||
const { login } = useAuth();
|
||||
const router = useRouter();
|
||||
|
||||
const handleAltchaStateChange = useCallback((state: any) => {
|
||||
if (state.state === 'verified' && state.payload) {
|
||||
setAltchaToken(state.payload);
|
||||
setAltchaVerified(true);
|
||||
} else {
|
||||
setAltchaToken('');
|
||||
setAltchaVerified(false);
|
||||
}
|
||||
const handleAltchaVerified = useCallback((payload: string) => {
|
||||
setAltchaToken(payload);
|
||||
setAltchaVerified(true);
|
||||
}, []);
|
||||
|
||||
const handleAltchaError = useCallback(() => {
|
||||
setAltchaToken('');
|
||||
setAltchaVerified(false);
|
||||
}, []);
|
||||
|
||||
const performLogin = useCallback(async () => {
|
||||
|
|
@ -107,7 +107,8 @@ export default function LoginPage() {
|
|||
<div>
|
||||
<Altcha
|
||||
challengeurl="https://api.sojorn.net/api/v1/admin/altcha-challenge"
|
||||
onStateChange={handleAltchaStateChange}
|
||||
onVerified={handleAltchaVerified}
|
||||
onError={handleAltchaError}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -1,58 +1,71 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useEffect, useRef, useCallback } from 'react';
|
||||
|
||||
interface AltchaProps {
|
||||
challengeurl: string;
|
||||
onStateChange?: (state: any) => void;
|
||||
onVerified?: (payload: string) => void;
|
||||
onError?: () => void;
|
||||
}
|
||||
|
||||
export default function Altcha({ challengeurl, onStateChange }: AltchaProps) {
|
||||
export default function Altcha({ challengeurl, onVerified, onError }: AltchaProps) {
|
||||
const widgetRef = useRef<HTMLDivElement>(null);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const scriptLoaded = useRef(false);
|
||||
|
||||
const handleStateChange = useCallback((e: Event) => {
|
||||
const detail = (e as CustomEvent).detail;
|
||||
if (detail?.state === 'verified' && detail?.payload) {
|
||||
onVerified?.(detail.payload);
|
||||
} else if (detail?.state === 'error') {
|
||||
onError?.();
|
||||
}
|
||||
}, [onVerified, onError]);
|
||||
|
||||
useEffect(() => {
|
||||
// Load ALTCHA widget script
|
||||
if (scriptLoaded.current) return;
|
||||
scriptLoaded.current = true;
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://cdn.jsdelivr.net/npm/altcha@0.5.0/dist/altcha.min.js';
|
||||
script.src = 'https://cdn.jsdelivr.net/npm/altcha@2.3.0/dist/altcha.min.js';
|
||||
script.type = 'module';
|
||||
script.async = true;
|
||||
script.onload = () => setLoaded(true);
|
||||
document.head.appendChild(script);
|
||||
|
||||
return () => {
|
||||
if (script.parentNode) {
|
||||
script.parentNode.removeChild(script);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loaded || !widgetRef.current) return;
|
||||
const container = widgetRef.current;
|
||||
if (!container) return;
|
||||
|
||||
const widget = widgetRef.current.querySelector('altcha-widget');
|
||||
if (!widget) return;
|
||||
|
||||
const handleStateChange = (event: any) => {
|
||||
if (onStateChange) {
|
||||
onStateChange(event.detail);
|
||||
const observer = new MutationObserver(() => {
|
||||
const widget = container.querySelector('altcha-widget');
|
||||
if (widget) {
|
||||
widget.addEventListener('statechange', handleStateChange);
|
||||
observer.disconnect();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
widget.addEventListener('statechange', handleStateChange);
|
||||
observer.observe(container, { childList: true, subtree: true });
|
||||
|
||||
// Also try immediately in case widget already exists
|
||||
const widget = container.querySelector('altcha-widget');
|
||||
if (widget) {
|
||||
widget.addEventListener('statechange', handleStateChange);
|
||||
observer.disconnect();
|
||||
}
|
||||
|
||||
return () => {
|
||||
widget.removeEventListener('statechange', handleStateChange);
|
||||
observer.disconnect();
|
||||
const w = container.querySelector('altcha-widget');
|
||||
if (w) {
|
||||
w.removeEventListener('statechange', handleStateChange);
|
||||
}
|
||||
};
|
||||
}, [loaded, onStateChange]);
|
||||
}, [handleStateChange]);
|
||||
|
||||
return (
|
||||
<div ref={widgetRef}>
|
||||
<altcha-widget
|
||||
challengeurl={challengeurl}
|
||||
hidefooter="true"
|
||||
hidelogo="true"
|
||||
/>
|
||||
</div>
|
||||
<div ref={widgetRef} dangerouslySetInnerHTML={{
|
||||
__html: `<altcha-widget challengeurl="${challengeurl}" debug></altcha-widget>`
|
||||
}} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue