From 2fd0eec156e10b404cb9eee4e28a3eb417c76cb0 Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Fri, 10 Jul 2026 14:55:12 +0330 Subject: [PATCH] fix: update Altcha component to properly set attributes and handle state changes --- components/Altcha.js | 36 +++++++++++++++++++----------------- next.config.js | 3 +++ 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/components/Altcha.js b/components/Altcha.js index 2c3093c..6ba82a7 100644 --- a/components/Altcha.js +++ b/components/Altcha.js @@ -30,35 +30,37 @@ export default function Altcha({ onVerified }) { }; }, [onVerified]); - // ثبت custom element + ست‌کردن config به‌صورت attribute واقعی. در React 18 - // پراپ‌های JSX روی custom element ممکن است به‌جای attribute به‌شکل property ست - // شوند و widget آن‌ها را نخواند (strings/theme اعمال نمی‌شد)؛ با setAttribute - // مطمئن می‌شویم درست خوانده می‌شوند. auto را آخر ست می‌کنیم تا بعد از config حل شود. useEffect(() => { if (enabled !== true) return; + const el = ref.current; + if (!el) return; + let cancelled = false; const onStateChange = (e) => { if (e.detail?.state === "verified" && e.detail.payload) { onVerified(e.detail.payload); } }; + el.addEventListener("statechange", onStateChange); - // attributeها را قبل از import (قبل از upgrade شدن element) ست می‌کنیم تا - // widget از همان ابتدا با تم روشن و متن فارسی init شود. locale رسمی fa با - // import ماژول i18n ثبت و با language="fa" فعال می‌شود (RTL هم خودکار است). - const el = ref.current; - if (el) { - el.setAttribute("challengeurl", `${API}/api/v1/altcha/challenge`); - el.setAttribute("language", "fa"); - el.setAttribute("theme", "light"); - el.setAttribute("auto", "onload"); - el.addEventListener("statechange", onStateChange); - } + // در React 18 پراپ‌های JSX روی custom element ممکن است property ست شوند و + // widget نخواند؛ پس با setAttribute ست می‌کنیم. نام attribute در widget v3 + // «challenge» است (نه «challengeurl» قدیمی که باعث fetch صفحه‌ی HTML می‌شد). + el.setAttribute("challenge", `${API}/api/v1/altcha/challenge`); + el.setAttribute("language", "fa"); + el.setAttribute("theme", "light"); - Promise.all([import("altcha/i18n/fa"), import("altcha")]); + // اول locale فارسی ثبت شود، سپس ماژول widget (تا هنگام upgrade، fa موجود باشد)، + // و در نهایت auto فعال شود تا حل PoW بعد از آماده‌بودن challenge/زبان انجام شود. + import("altcha/i18n/fa") + .then(() => import("altcha")) + .then(() => { + if (!cancelled) el.setAttribute("auto", "onload"); + }); return () => { - el?.removeEventListener("statechange", onStateChange); + cancelled = true; + el.removeEventListener("statechange", onStateChange); }; }, [enabled, onVerified]); diff --git a/next.config.js b/next.config.js index 563f6bf..87289c7 100644 --- a/next.config.js +++ b/next.config.js @@ -63,6 +63,9 @@ const nextConfig = { "default-src 'self'", "img-src 'self' https: data: blob:", "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com", + // ALTCHA کپچا برای حل proof-of-work از Web Workerِ blob استفاده می‌کند؛ + // بدون این، worker بلاک و کپچا «احراز هویت ناموفق» می‌دهد. + "worker-src 'self' blob:", "style-src 'self' 'unsafe-inline'", "font-src 'self' data:", 'connect-src ' + connectSrc,