Add simple camera test component for debugging
🔬 Camera Debug Test: - Create minimal camera component to isolate UI issues - Always shows video element (no conditional rendering) - Detailed status and error reporting - Shows video properties and ready state - Tests basic camera stream assignment and playback This will help determine if the issue is: ❓ Video element not rendering at all ❓ Stream not being assigned properly ❓ CSS/styling hiding the video ❓ Video element exists but shows black screen
This commit is contained in:
parent
7e4d59b02e
commit
02c83fb52f
2 changed files with 114 additions and 0 deletions
110
src/components/SimpleCameraTest.tsx
Normal file
110
src/components/SimpleCameraTest.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
|
||||||
|
const SimpleCameraTest: React.FC = () => {
|
||||||
|
const [stream, setStream] = useState<MediaStream | null>(null);
|
||||||
|
const [error, setError] = useState<string>('');
|
||||||
|
const [status, setStatus] = useState<string>('Not started');
|
||||||
|
const videoRef = useRef<HTMLVideoElement>(null);
|
||||||
|
|
||||||
|
const startCamera = async () => {
|
||||||
|
setStatus('🔄 Starting camera...');
|
||||||
|
setError('');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const mediaStream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
video: { facingMode: 'environment' }
|
||||||
|
});
|
||||||
|
|
||||||
|
setStatus('✅ Camera stream obtained');
|
||||||
|
setStream(mediaStream);
|
||||||
|
|
||||||
|
if (videoRef.current) {
|
||||||
|
videoRef.current.srcObject = mediaStream;
|
||||||
|
setStatus('✅ Stream assigned to video element');
|
||||||
|
|
||||||
|
// Force play
|
||||||
|
videoRef.current.play().then(() => {
|
||||||
|
setStatus('✅ Video playing successfully');
|
||||||
|
}).catch((err) => {
|
||||||
|
setError(`Play error: ${err.message}`);
|
||||||
|
setStatus('❌ Video play failed');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setError('Video ref is null');
|
||||||
|
setStatus('❌ No video element');
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
setError(`Camera error: ${err.message}`);
|
||||||
|
setStatus('❌ Camera failed');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopCamera = () => {
|
||||||
|
if (stream) {
|
||||||
|
stream.getTracks().forEach(track => track.stop());
|
||||||
|
setStream(null);
|
||||||
|
}
|
||||||
|
setStatus('Camera stopped');
|
||||||
|
setError('');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-4 border border-gray-300 rounded-lg">
|
||||||
|
<h3 className="font-bold mb-4">🔬 Simple Camera Test</h3>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<button
|
||||||
|
onClick={startCamera}
|
||||||
|
className="bg-green-600 text-white px-4 py-2 rounded"
|
||||||
|
disabled={!!stream}
|
||||||
|
>
|
||||||
|
Start Camera
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={stopCamera}
|
||||||
|
className="bg-red-600 text-white px-4 py-2 rounded"
|
||||||
|
disabled={!stream}
|
||||||
|
>
|
||||||
|
Stop Camera
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-sm">
|
||||||
|
<div><strong>Status:</strong> {status}</div>
|
||||||
|
{error && <div className="text-red-600"><strong>Error:</strong> {error}</div>}
|
||||||
|
<div><strong>Stream:</strong> {stream ? '✅ Active' : '❌ None'}</div>
|
||||||
|
<div><strong>Video Ref:</strong> {videoRef.current ? '✅ Exists' : '❌ Null'}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Always show video element */}
|
||||||
|
<div className="bg-black rounded-lg overflow-hidden">
|
||||||
|
<video
|
||||||
|
ref={videoRef}
|
||||||
|
autoPlay
|
||||||
|
playsInline
|
||||||
|
muted
|
||||||
|
className="w-full h-auto max-h-64 object-cover"
|
||||||
|
style={{ minHeight: '200px' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Debug info */}
|
||||||
|
<div className="text-xs bg-gray-100 p-2 rounded">
|
||||||
|
<div>Video element exists: {videoRef.current ? 'Yes' : 'No'}</div>
|
||||||
|
{videoRef.current && (
|
||||||
|
<>
|
||||||
|
<div>Video width: {videoRef.current.videoWidth}</div>
|
||||||
|
<div>Video height: {videoRef.current.videoHeight}</div>
|
||||||
|
<div>Ready state: {videoRef.current.readyState}</div>
|
||||||
|
<div>Paused: {videoRef.current.paused ? 'Yes' : 'No'}</div>
|
||||||
|
<div>Muted: {videoRef.current.muted ? 'Yes' : 'No'}</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SimpleCameraTest;
|
||||||
|
|
@ -3,6 +3,7 @@ import CameraScanner from '../components/CameraScanner';
|
||||||
import GlowingCard from '../components/GlowingCard';
|
import GlowingCard from '../components/GlowingCard';
|
||||||
import CardImageDisplay from '../components/CardImageDisplay';
|
import CardImageDisplay from '../components/CardImageDisplay';
|
||||||
import DebugInfo from '../components/DebugInfo';
|
import DebugInfo from '../components/DebugInfo';
|
||||||
|
import SimpleCameraTest from '../components/SimpleCameraTest';
|
||||||
import { cardMatcher } from '../services/cardMatcher';
|
import { cardMatcher } from '../services/cardMatcher';
|
||||||
import { useAuth } from '../contexts/AuthContext';
|
import { useAuth } from '../contexts/AuthContext';
|
||||||
|
|
||||||
|
|
@ -279,6 +280,9 @@ const Scanner: React.FC = () => {
|
||||||
{/* Debug Information */}
|
{/* Debug Information */}
|
||||||
<DebugInfo />
|
<DebugInfo />
|
||||||
|
|
||||||
|
{/* Simple Camera Test */}
|
||||||
|
<SimpleCameraTest />
|
||||||
|
|
||||||
{/* Error Display */}
|
{/* Error Display */}
|
||||||
{error && (
|
{error && (
|
||||||
<div className="mb-6 bg-red-50 border border-red-200 rounded-lg p-4">
|
<div className="mb-6 bg-red-50 border border-red-200 rounded-lg p-4">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue