Skip to content

Commit 7d385bd

Browse files
committed
fix: default to back camera
1 parent 5023b7b commit 7d385bd

File tree

1 file changed

+62
-27
lines changed

1 file changed

+62
-27
lines changed

src/app/search/page.tsx

Lines changed: 62 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ export default function ProductSearch() {
8080

8181
// Filter cameras to only include back, front, and ultrawide
8282
const filterCameras = async (devices: MediaDeviceInfo[]): Promise<MediaDeviceInfo[]> => {
83-
const filtered: MediaDeviceInfo[] = [];
83+
const backCameras: MediaDeviceInfo[] = [];
84+
const frontCameras: MediaDeviceInfo[] = [];
85+
const ultrawideCameras: MediaDeviceInfo[] = [];
8486

8587
// First, try to get proper camera permissions to ensure device labels are available
8688
let permissionGranted = false;
@@ -120,72 +122,98 @@ export default function ProductSearch() {
120122
const label = device.label.toLowerCase();
121123
const facingMode = settings.facingMode || capabilities.facingMode;
122124

123-
// Include back camera (main camera)
125+
// Categorize cameras
124126
if (facingMode === 'environment' ||
125127
label.includes('back') ||
126128
label.includes('rear') ||
127129
(!label.includes('front') && !label.includes('selfie') && devices.indexOf(device) === 0)) {
128-
filtered.push(device);
130+
backCameras.push(device);
129131
}
130-
// Include front camera
131132
else if (facingMode === 'user' ||
132133
label.includes('front') ||
133134
label.includes('selfie')) {
134-
filtered.push(device);
135+
frontCameras.push(device);
135136
}
136-
// Include ultrawide camera
137137
else if (label.includes('ultra') ||
138138
label.includes('wide') ||
139139
label.includes('0.5')) {
140-
filtered.push(device);
140+
ultrawideCameras.push(device);
141141
}
142142
} else {
143143
// Fallback: use label-based filtering without stream access
144144
const label = device.label.toLowerCase();
145145
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);
146+
label.includes('rear') ||
147+
(!label.includes('front') && !label.includes('selfie') && devices.indexOf(device) === 0)) {
148+
backCameras.push(device);
149+
}
150+
else if (label.includes('front') ||
151+
label.includes('selfie')) {
152+
frontCameras.push(device);
153+
}
154+
else if (label.includes('ultra') ||
155+
label.includes('wide') ||
156+
label.includes('0.5')) {
157+
ultrawideCameras.push(device);
153158
}
154159
}
155160
} catch {
156161
// If we can't get capabilities, use label-based filtering
157162
const label = device.label.toLowerCase();
158163
if (label.includes('back') ||
159-
label.includes('rear') ||
160-
label.includes('front') ||
161-
label.includes('selfie') ||
162-
label.includes('ultra') ||
163-
label.includes('wide') ||
164-
(!label.includes('front') && devices.indexOf(device) === 0)) {
165-
filtered.push(device);
164+
label.includes('rear') ||
165+
(!label.includes('front') && !label.includes('selfie') && devices.indexOf(device) === 0)) {
166+
backCameras.push(device);
167+
}
168+
else if (label.includes('front') ||
169+
label.includes('selfie')) {
170+
frontCameras.push(device);
171+
}
172+
else if (label.includes('ultra') ||
173+
label.includes('wide') ||
174+
label.includes('0.5')) {
175+
ultrawideCameras.push(device);
166176
}
167177
}
168178
}
169179

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) {
180+
// Build filtered array with back camera first, then front, then ultrawide
181+
const filtered: MediaDeviceInfo[] = [];
182+
183+
// Add back cameras first (prioritize main back camera)
184+
if (backCameras.length > 0) {
185+
filtered.push(backCameras[0]); // Main back camera
186+
}
187+
188+
// Add front camera second
189+
if (frontCameras.length > 0) {
190+
filtered.push(frontCameras[0]); // Main front camera
191+
}
192+
193+
// Add ultrawide camera third (if available)
194+
if (ultrawideCameras.length > 0) {
195+
filtered.push(ultrawideCameras[0]); // First ultrawide camera
196+
}
197+
198+
// Mobile device fallback: if no cameras were categorized properly
199+
if (filtered.length === 0 && devices.length >= 2 && !permissionGranted) {
173200
// On mobile, typically the first device is back camera, second is front
174-
filtered.length = 0; // Clear filtered array
175201
filtered.push(devices[0]); // Back camera (usually)
176202
if (devices.length > 1) {
177203
filtered.push(devices[1]); // Front camera (usually)
178204
}
179-
// Add any additional cameras that might be ultrawide
205+
206+
// Only add one more camera if it might be ultrawide
180207
for (let i = 2; i < devices.length; i++) {
181208
const label = devices[i].label.toLowerCase();
182209
if (label.includes('ultra') || label.includes('wide') || label.includes('0.5')) {
183210
filtered.push(devices[i]);
211+
break; // Only add one additional camera
184212
}
185213
}
186214
}
187215

188-
// If no cameras matched our criteria, fall back to first available camera
216+
// Final fallback: if no cameras matched our criteria, fall back to first available camera
189217
if (filtered.length === 0 && devices.length > 0) {
190218
filtered.push(devices[0]);
191219
}
@@ -286,6 +314,13 @@ export default function ProductSearch() {
286314
};
287315
}, [router, pageLoading, currentCameraIndex]);
288316

317+
// Separate effect to initialize camera index when cameras are first detected
318+
useEffect(() => {
319+
if (filteredCameras.length > 0 && currentCameraIndex !== 0) {
320+
setCurrentCameraIndex(0); // Always start with back camera (index 0)
321+
}
322+
}, [filteredCameras, currentCameraIndex]);
323+
289324
// Cleanup camera when component unmounts
290325
useEffect(() => {
291326
return () => {

0 commit comments

Comments
 (0)