From 7489b611b066333c8af2c0032f3533ff9c2b540c Mon Sep 17 00:00:00 2001 From: admtracksteel Date: Sat, 30 May 2026 11:48:45 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Auto-deploy:=20melhoria=20no=20s?= =?UTF-8?q?nap=20e=20medi=C3=A7=C3=A3o=20AR=20em=2030/05/2026=2011:48:45?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Viewer.tsx | 6 +++- src/pages/XRSession.tsx | 65 +++++++++++----------------------------- src/stores/useXRStore.ts | 39 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 49 deletions(-) create mode 100644 src/stores/useXRStore.ts diff --git a/src/pages/Viewer.tsx b/src/pages/Viewer.tsx index bb549dd..06ee5ca 100644 --- a/src/pages/Viewer.tsx +++ b/src/pages/Viewer.tsx @@ -223,7 +223,11 @@ const Viewer = () => { toast.error("WebXR não é suportado neste navegador. Use o navegador do Meta Quest 3."); return; } - navigate("/xr"); + // Entra diretamente no AR para não perder o clique do usuário! + import('@/stores/useXRStore').then(({ xrStore }) => { + xrStore.enterAR().catch(e => console.error('[Viewer] XR enterAR error:', e)); + navigate("/xr"); + }); }; const handleEnterMeeting = () => { diff --git a/src/pages/XRSession.tsx b/src/pages/XRSession.tsx index 7abac38..5c02aac 100644 --- a/src/pages/XRSession.tsx +++ b/src/pages/XRSession.tsx @@ -2,7 +2,8 @@ import { useEffect, useRef, useMemo, useCallback, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Canvas, useFrame, useThree } from '@react-three/fiber'; import { useGLTF, Grid, Html, Line, OrbitControls, Text } from '@react-three/drei'; -import { XR, createXRStore, useXR, XROrigin, useXRHitTest } from '@react-three/xr'; +import { XR, useXR, XROrigin, useXRHitTest } from '@react-three/xr'; +import { xrStore as store } from '@/stores/useXRStore'; import * as THREE from 'three'; import { useModelStore } from '@/stores/useModelStore'; import { toast } from 'sonner'; @@ -45,39 +46,7 @@ if (navigator.xr) { }); } -// Lê flags de feature WebXR do localStorage (default: todas ON). -// O usuário liga/desliga pelo HUD AR (aba WebXR) para diagnosticar qual -// feature ativa o grid de segurança do Quest. Mudanças exigem sair e re-entrar do AR. -function loadXRFeatures() { - const defaults = { - handTracking: true, planeDetection: true, hitTest: true, domOverlay: true, - anchors: true, meshDetection: true, depthSensing: true, layers: true, - bodyTracking: true, lightEstimation: true, - }; - try { - const raw = localStorage.getItem('xrFeatures'); - if (raw) return { ...defaults, ...JSON.parse(raw) }; - } catch (err) { - console.warn('[XR] Falha ao ler xrFeatures do localStorage:', err); - } - return defaults; -} -const _xrf = loadXRFeatures(); -console.log('[XR] Features:', _xrf); - -const store = createXRStore({ - hand: { left: true, right: true }, - controller: { left: true, right: true }, - handTracking: _xrf.handTracking, - planeDetection: _xrf.planeDetection, - hitTest: _xrf.hitTest, - domOverlay: _xrf.domOverlay, - anchors: _xrf.anchors, - meshDetection: _xrf.meshDetection, - depthSensing: _xrf.depthSensing, - layers: _xrf.layers, - bodyTracking: _xrf.bodyTracking, -}); +// `store` is now imported from `@/stores/useXRStore` // ─── XRModel ─────────────────────────────────────────── function XRModel({ sceneModel }: { sceneModel: import('@/stores/useModelStore').SceneModel }) { @@ -1113,6 +1082,20 @@ const XRSession = () => { if (!model) return null; + // Auto-return to viewer if user exits AR session + useEffect(() => { + // If we are mounted, and the session is completely absent/ended (inXR is false), + // we wait a brief moment to avoid returning during initial transition, then return. + if (!inXR) { + const timer = setTimeout(() => { + if (!store.getState().session) { + navigate('/viewer'); + } + }, 500); + return () => clearTimeout(timer); + } + }, [inXR, navigate]); + return (
{/* Header */} @@ -1130,20 +1113,6 @@ const XRSession = () => {
- {!inXR && ( - <> - - - - )} {inXR && ( diff --git a/src/stores/useXRStore.ts b/src/stores/useXRStore.ts new file mode 100644 index 0000000..fadfeb5 --- /dev/null +++ b/src/stores/useXRStore.ts @@ -0,0 +1,39 @@ +import { createXRStore } from '@react-three/xr'; + +function loadXRFeatures() { + const defaults = { + handTracking: true, + planeDetection: true, + hitTest: true, + domOverlay: true, + anchors: true, + meshDetection: true, + depthSensing: true, + layers: true, + bodyTracking: true, + lightEstimation: true, + }; + try { + const raw = localStorage.getItem('xrFeatures'); + if (raw) return { ...defaults, ...JSON.parse(raw) }; + } catch (err) { + console.warn('[XR] Falha ao ler xrFeatures do localStorage:', err); + } + return defaults; +} + +const _xrf = loadXRFeatures(); + +export const xrStore = createXRStore({ + hand: { left: true, right: true }, + controller: { left: true, right: true }, + handTracking: _xrf.handTracking, + planeDetection: _xrf.planeDetection, + hitTest: _xrf.hitTest, + domOverlay: _xrf.domOverlay, + anchors: _xrf.anchors, + meshDetection: _xrf.meshDetection, + depthSensing: _xrf.depthSensing, + layers: _xrf.layers, + bodyTracking: _xrf.bodyTracking, +});