diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index 39facad..5b1a841 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -365,7 +365,7 @@ const Index = () => { {/* Footer */}
- SteelXR v1.11 — Q.C. Inspection + SteelXR v1.12 — Q.C. Inspection
{showLogs && ( diff --git a/src/pages/Viewer.tsx b/src/pages/Viewer.tsx index 612c863..fd542fd 100644 --- a/src/pages/Viewer.tsx +++ b/src/pages/Viewer.tsx @@ -259,37 +259,12 @@ const Viewer = () => { const [enteringXR, setEnteringXR] = useState(false); - const handleEnterXR = useCallback(async () => { + const handleEnterXR = useCallback(() => { if (!xrSupported) { toast.error("WebXR não é suportado neste navegador. Use o navegador do Meta Quest 3."); return; } - setEnteringXR(true); - - // Timeout de segurança — se não entrar em 15s, cancela - const timeoutId = setTimeout(() => { - setEnteringXR(false); - toast.error("Tempo limite ao iniciar modo AR. Verifique se o Meta Quest Browser está conectado."); - }, 15000); - - try { - // Marca que está entrando no AR antes de navegar — bloqueia auto-return prematuro - (window as unknown as { __setXrEntering?: (v: boolean) => void }).__setXrEntering?.(true); - - // Chamada síncrona de enterAR para preservar o User Gesture exigido pelo WebXR - const enterPromise = xrStore.enterAR(); - - clearTimeout(timeoutId); - navigate("/xr"); - - await enterPromise; - } catch (e) { - clearTimeout(timeoutId); - setEnteringXR(false); - (window as unknown as { __setXrEntering?: (v: boolean) => void }).__setXrEntering?.(false); - console.error('[Viewer] XR enterAR error:', e); - toast.error("Falha ao iniciar modo AR. Verifique se o Meta Quest Browser está conectado."); - } + navigate("/xr"); }, [xrSupported, navigate]); const handleEnterMeeting = () => { diff --git a/src/pages/XRSession.tsx b/src/pages/XRSession.tsx index 323ba88..34f7042 100644 --- a/src/pages/XRSession.tsx +++ b/src/pages/XRSession.tsx @@ -7,7 +7,7 @@ import { xrStore as store } from '@/stores/useXRStore'; import * as THREE from 'three'; import { useModelStore } from '@/stores/useModelStore'; import { toast } from 'sonner'; -import { ArrowLeft, Download, QrCode, Crosshair, Home } from 'lucide-react'; +import { ArrowLeft, Download, QrCode, Crosshair, Home, Glasses } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { generateMarkerDownloadURL } from '@/lib/trackingMarker'; import { XRHud } from '@/components/XRHud'; @@ -1050,6 +1050,7 @@ const XRSession = () => { const effectiveInXR = inXR || simXR; // Indica que enterAR() foi chamado mas a sessão ainda não começou — previne auto-return prematuro const [isEnteringAR, setIsEnteringAR] = useState(false); + const [hasClickedEnter, setHasClickedEnter] = useState(false); useEffect(() => { if (!model) navigate('/'); @@ -1098,12 +1099,10 @@ const XRSession = () => { toast.success('Marcador baixado — Imprima em 15×15cm'); }, []); - if (!model) return null; - // Auto-return to viewer if user exits AR session useEffect(() => { // Don't auto-return while we're waiting for the XR onboarding dialog to complete - if (!inXR) { + if (hasClickedEnter && !inXR) { const timer = setTimeout(() => { // Only return if the session is truly absent AND we're not in the middle of entering AR if (!store.getState().session) { @@ -1112,7 +1111,9 @@ const XRSession = () => { }, 2000); return () => clearTimeout(timer); } - }, [inXR, navigate]); + }, [inXR, hasClickedEnter, navigate]); + + if (!model) return null; return (+ Você está prestes a carregar o modelo em escala real 1:1 no seu ambiente físico. +
+