Skip to content

Commit 5023b7b

Browse files
committed
fix: fixed cameras when first loaded
1 parent 8d39d0b commit 5023b7b

File tree

1 file changed

+85
-34
lines changed

1 file changed

+85
-34
lines changed

src/app/search/page.tsx

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -82,42 +82,75 @@ export default function ProductSearch() {
8282
const filterCameras = async (devices: MediaDeviceInfo[]): Promise<MediaDeviceInfo[]> => {
8383
const filtered: MediaDeviceInfo[] = [];
8484

85+
// First, try to get proper camera permissions to ensure device labels are available
86+
let permissionGranted = false;
87+
try {
88+
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
89+
stream.getTracks().forEach(track => track.stop());
90+
permissionGranted = true;
91+
92+
// Re-enumerate devices after permission is granted to get proper labels
93+
const devicesWithLabels = await navigator.mediaDevices.enumerateDevices();
94+
const videoDevices = devicesWithLabels.filter(device => device.kind === 'videoinput');
95+
96+
// Use the devices with proper labels if available
97+
if (videoDevices.length > 0) {
98+
devices = videoDevices;
99+
}
100+
} catch {
101+
// Permission denied or not available, continue with existing devices
102+
}
103+
85104
for (const device of devices) {
86105
try {
87-
// Get camera capabilities to determine facing mode
88-
const stream = await navigator.mediaDevices.getUserMedia({
89-
video: { deviceId: device.deviceId }
90-
});
91-
92-
const track = stream.getVideoTracks()[0];
93-
const capabilities = track.getCapabilities();
94-
const settings = track.getSettings();
95-
96-
// Stop the stream immediately
97-
stream.getTracks().forEach(track => track.stop());
98-
99-
// Check for facing mode or camera type in label
100-
const label = device.label.toLowerCase();
101-
const facingMode = settings.facingMode || capabilities.facingMode;
102-
103-
// Include back camera (main camera)
104-
if (facingMode === 'environment' ||
105-
label.includes('back') ||
106-
label.includes('rear') ||
107-
(!label.includes('front') && !label.includes('selfie') && devices.indexOf(device) === 0)) {
108-
filtered.push(device);
109-
}
110-
// Include front camera
111-
else if (facingMode === 'user' ||
112-
label.includes('front') ||
113-
label.includes('selfie')) {
114-
filtered.push(device);
115-
}
116-
// Include ultrawide camera
117-
else if (label.includes('ultra') ||
118-
label.includes('wide') ||
119-
label.includes('0.5')) {
120-
filtered.push(device);
106+
// Get camera capabilities to determine facing mode (only if permission granted)
107+
if (permissionGranted) {
108+
const stream = await navigator.mediaDevices.getUserMedia({
109+
video: { deviceId: device.deviceId }
110+
});
111+
112+
const track = stream.getVideoTracks()[0];
113+
const capabilities = track.getCapabilities();
114+
const settings = track.getSettings();
115+
116+
// Stop the stream immediately
117+
stream.getTracks().forEach(track => track.stop());
118+
119+
// Check for facing mode or camera type in label
120+
const label = device.label.toLowerCase();
121+
const facingMode = settings.facingMode || capabilities.facingMode;
122+
123+
// Include back camera (main camera)
124+
if (facingMode === 'environment' ||
125+
label.includes('back') ||
126+
label.includes('rear') ||
127+
(!label.includes('front') && !label.includes('selfie') && devices.indexOf(device) === 0)) {
128+
filtered.push(device);
129+
}
130+
// Include front camera
131+
else if (facingMode === 'user' ||
132+
label.includes('front') ||
133+
label.includes('selfie')) {
134+
filtered.push(device);
135+
}
136+
// Include ultrawide camera
137+
else if (label.includes('ultra') ||
138+
label.includes('wide') ||
139+
label.includes('0.5')) {
140+
filtered.push(device);
141+
}
142+
} else {
143+
// Fallback: use label-based filtering without stream access
144+
const label = device.label.toLowerCase();
145+
if (label.includes('back') ||
146+
label.includes('rear') ||
147+
label.includes('front') ||
148+
label.includes('selfie') ||
149+
label.includes('ultra') ||
150+
label.includes('wide') ||
151+
(!label.includes('front') && devices.indexOf(device) === 0)) {
152+
filtered.push(device);
153+
}
121154
}
122155
} catch {
123156
// If we can't get capabilities, use label-based filtering
@@ -134,6 +167,24 @@ export default function ProductSearch() {
134167
}
135168
}
136169

170+
// Mobile device fallback: if we have multiple devices but filtering returned few,
171+
// and no permissions were granted, include more devices
172+
if (filtered.length < 2 && devices.length >= 2 && !permissionGranted) {
173+
// On mobile, typically the first device is back camera, second is front
174+
filtered.length = 0; // Clear filtered array
175+
filtered.push(devices[0]); // Back camera (usually)
176+
if (devices.length > 1) {
177+
filtered.push(devices[1]); // Front camera (usually)
178+
}
179+
// Add any additional cameras that might be ultrawide
180+
for (let i = 2; i < devices.length; i++) {
181+
const label = devices[i].label.toLowerCase();
182+
if (label.includes('ultra') || label.includes('wide') || label.includes('0.5')) {
183+
filtered.push(devices[i]);
184+
}
185+
}
186+
}
187+
137188
// If no cameras matched our criteria, fall back to first available camera
138189
if (filtered.length === 0 && devices.length > 0) {
139190
filtered.push(devices[0]);

0 commit comments

Comments
 (0)