Simplified XR store setup
Refactored XRSession to remove marker bitmap preloading and lazy async store initialization. Replaced complex getXRStore flow with a single getOrCreateXRStore, removed manual bitmap handling, and updated AR start flow to use the centralized store. Simplified UX message on successful XR start. X-Lovable-Edit-ID: edt-a8250c81-169f-4cc7-8370-4f5068a2c078
This commit is contained in:
+7
-54
@@ -8,55 +8,15 @@ import { useModelStore } from '@/stores/useModelStore';
|
||||
import { toast } from 'sonner';
|
||||
import { ArrowLeft, Move, RotateCw, QrCode, Download, Crosshair } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { generateTrackingMarker, generateMarkerDownloadURL } from '@/lib/trackingMarker';
|
||||
import { generateMarkerDownloadURL } from '@/lib/trackingMarker';
|
||||
|
||||
// --- Marker bitmap singleton ---
|
||||
let markerBitmapPromise: Promise<ImageBitmap> | null = null;
|
||||
function getMarkerBitmap(): Promise<ImageBitmap> {
|
||||
if (!markerBitmapPromise) {
|
||||
markerBitmapPromise = generateTrackingMarker();
|
||||
}
|
||||
return markerBitmapPromise;
|
||||
}
|
||||
|
||||
// --- XR Store singleton (lazy-initialized with marker) ---
|
||||
// --- XR Store singleton ---
|
||||
let xrStoreInstance: ReturnType<typeof createXRStore> | null = null;
|
||||
|
||||
async function getXRStore() {
|
||||
function getOrCreateXRStore() {
|
||||
if (xrStoreInstance) return xrStoreInstance;
|
||||
|
||||
const bitmap = await getMarkerBitmap();
|
||||
|
||||
// Only emulate when on localhost AND no native XR support
|
||||
const shouldEmulate =
|
||||
typeof window !== 'undefined' &&
|
||||
window.location.hostname === 'localhost' &&
|
||||
!navigator.xr;
|
||||
|
||||
xrStoreInstance = createXRStore({
|
||||
emulate: shouldEmulate ? 'metaQuest3' : false,
|
||||
hand: { left: true, right: true },
|
||||
controller: { left: true, right: true },
|
||||
customSessionInit: {
|
||||
optionalFeatures: ['image-tracking'],
|
||||
// @ts-ignore — trackedImages is a WebXR extension not yet in TS types
|
||||
trackedImages: [
|
||||
{
|
||||
image: bitmap,
|
||||
widthInMeters: 0.15, // 15cm printed marker
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
return xrStoreInstance;
|
||||
}
|
||||
|
||||
// Create a synchronous fallback store for initial render
|
||||
// (will be replaced once the async one is ready)
|
||||
function getInitialXRStore() {
|
||||
if (xrStoreInstance) return xrStoreInstance;
|
||||
|
||||
const shouldEmulate =
|
||||
typeof window !== 'undefined' &&
|
||||
window.location.hostname === 'localhost' &&
|
||||
@@ -243,24 +203,17 @@ const XRSession = () => {
|
||||
const navigate = useNavigate();
|
||||
const { model, anchorMode, setAnchorMode } = useModelStore();
|
||||
const [inXR, setInXR] = useState(false);
|
||||
const [store, setStore] = useState(() => getInitialXRStore());
|
||||
const [store] = useState(() => getOrCreateXRStore());
|
||||
|
||||
// Pre-load marker and rebuild store with customSessionInit
|
||||
useEffect(() => {
|
||||
if (!model) {
|
||||
navigate('/');
|
||||
return;
|
||||
}
|
||||
getXRStore().then((s) => {
|
||||
// Update store ref if it was replaced with the marker-enabled one
|
||||
if (s !== store) setStore(s);
|
||||
});
|
||||
}, [model, navigate]);
|
||||
|
||||
const handleEnterAR = useCallback(async () => {
|
||||
try {
|
||||
const s = await getXRStore();
|
||||
const session = await s.enterAR();
|
||||
const session = await store.enterAR();
|
||||
if (session) {
|
||||
session.addEventListener('end', () => {
|
||||
setInXR(false);
|
||||
@@ -268,13 +221,13 @@ const XRSession = () => {
|
||||
});
|
||||
setInXR(true);
|
||||
setAnchorMode('manual');
|
||||
toast.success('Sessão XR iniciada — Buscando QR Code…');
|
||||
toast.success('Sessão XR iniciada!');
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error('XR error:', err);
|
||||
toast.error(`Falha ao iniciar XR: ${err.message}`);
|
||||
}
|
||||
}, [setAnchorMode]);
|
||||
}, [store, setAnchorMode]);
|
||||
|
||||
const handleDownloadMarker = useCallback(async () => {
|
||||
const url = await generateMarkerDownloadURL();
|
||||
|
||||
Reference in New Issue
Block a user