diff --git a/app/qr-ar/ar-viewer.tsx b/app/qr-ar/ar-viewer.tsx index 8d99b07..b43847e 100644 --- a/app/qr-ar/ar-viewer.tsx +++ b/app/qr-ar/ar-viewer.tsx @@ -1,8 +1,8 @@ 'use client'; - import { useEffect, useRef, useState } from 'react'; import { useParams } from 'react-router'; -import { supabase } from '~/lib/supabase'; +import { Box } from 'lucide-react'; +import { pb } from '~/lib/pocketbase'; // --- A-FRAME/AR.JS CUSTOM ELEMENTS TYPING FIX --- declare module 'react' { @@ -47,30 +47,31 @@ declare module 'react' { } } +const AR_HINTS = [ + 'Arranging models to view…', + 'Find a flat surface & step back…', + 'Keep your camera steady…', + 'Almost ready, clear some space…', + 'Preparing your AR experience…', +]; + export default function ARViewer() { const { id } = useParams(); - const modelViewerRef = useRef(null); - + const modelViewerRef = useRef(null); const [asset, setAsset] = useState(null); const [scriptLoaded, setScriptLoaded] = useState(false); + const [arLoading, setArLoading] = useState(false); + const [showHints, setShowHints] = useState(false); + const [hintIndex, setHintIndex] = useState(0); + const hintIntervalRef = useRef | null>(null); + const hintDelayRef = useRef | null>(null); useEffect(() => { if (!id) return; - const loadAsset = async () => { - const { data, error } = await supabase - .from('ar_assets') - .select('*') - .eq('id', id) - .single(); - - console.log('Supabase response:', { data, error }); - - if (!error && data) { - setAsset(data); - } + const data = await pb.collection('ar_assets').getOne(id); + if (data) setAsset(data); }; - loadAsset(); }, [id]); @@ -79,55 +80,140 @@ export default function ARViewer() { setScriptLoaded(true); return; } - const script = document.createElement('script'); script.id = 'model-viewer-script'; script.type = 'module'; - script.src = - 'https://ajax.googleapis.com/ajax/libs/model-viewer/3.4.0/model-viewer.min.js'; - - script.onload = () => { - console.log('model-viewer loaded'); - setScriptLoaded(true); - }; - + script.src = 'https://ajax.googleapis.com/ajax/libs/model-viewer/3.4.0/model-viewer.min.js'; + script.onload = () => setScriptLoaded(true); document.head.appendChild(script); }, []); - if (!scriptLoaded) { + const handleARClick = () => { + const mv = modelViewerRef.current as any; + if (!mv?.activateAR || arLoading) return; + + setArLoading(true); + setShowHints(false); + setHintIndex(0); + mv.activateAR(); + + const cleanup = () => { + setArLoading(false); + setShowHints(false); + if (hintIntervalRef.current) clearInterval(hintIntervalRef.current); + if (hintDelayRef.current) clearTimeout(hintDelayRef.current); + }; + + // Only show hints if AR is still loading after 1.5s + hintDelayRef.current = setTimeout(() => { + setShowHints(true); + hintIntervalRef.current = setInterval(() => { + setHintIndex((prev) => (prev + 1) % AR_HINTS.length); + }, 2000); + }, 1500); + + const onArStatus = (e: any) => { + const { status } = e.detail ?? {}; + if ( + status === 'session-started' || + status === 'object-placed' || + status === 'failed' || + status === 'not-presenting' + ) { + cleanup(); + mv.removeEventListener('ar-status', onArStatus); + } + }; + mv.addEventListener('ar-status', onArStatus); + + // Fallback reset after 15s + setTimeout(cleanup, 15000); + }; + + const glbUrl = asset?.glb_file + ? pb.files.getURL(asset, asset.glb_file) + : asset?.glb_url; + + const usdzUrl = asset?.usdz_file + ? pb.files.getURL(asset, asset.usdz_file) + : asset?.usdz_url; + + if (!scriptLoaded || !asset) { return ( -
-                Loading AR Viewer…
-                {'\n\n'}
-                asset: {JSON.stringify(asset, null, 2)}
-                {'\n'}
-                scriptLoaded: {String(scriptLoaded)}
-                {'\n'}
-                id: {String(id)}
-            
+
+
+

Loading AR Experience…

+
); } + return ( - { - console.error('Model viewer error:', e); - console.error('Failed to load:', asset?.glb_url); - }} - onLoad={() => console.log('Model loaded successfully')} - /> - //
- // Id : {asset?.id} - // AR Viewer for asset: {asset?.name} - // glb URL: {asset?.glb_url} - // usdz URL: {asset?.usdz_url} - //
+
+ + + { + console.error('Model viewer error:', e); + console.error('Failed to load:', glbUrl); + }} + onLoad={() => console.log('Model loaded successfully')} + /> + +
+ {asset?.name && ( + + {asset.name} + + )} +
+ t. +
+
+ +
+ +
+
); -} +} \ No newline at end of file