@@ -78,7 +78,7 @@ export default function ProductSearch() {
7878
7979 const debouncedQuery = useDebounce ( query , 500 ) ; // Increased debounce delay
8080
81- // Filter cameras to only include back, front, and ultrawide
81+ // Filter cameras to select exactly one back camera and one front camera
8282 const filterCameras = async ( devices : MediaDeviceInfo [ ] ) : Promise < MediaDeviceInfo [ ] > => {
8383 const backCameras : MediaDeviceInfo [ ] = [ ] ;
8484 const frontCameras : MediaDeviceInfo [ ] = [ ] ;
@@ -122,100 +122,104 @@ export default function ProductSearch() {
122122 const label = device . label . toLowerCase ( ) ;
123123 const facingMode = settings . facingMode || capabilities . facingMode ;
124124
125- // Categorize cameras
126- if ( facingMode === 'environment' ||
127- label . includes ( 'back' ) ||
128- label . includes ( 'rear' ) ||
129- ( ! label . includes ( 'front' ) && ! label . includes ( 'selfie' ) && devices . indexOf ( device ) === 0 ) ) {
130- backCameras . push ( device ) ;
131- }
132- else if ( facingMode === 'user' ||
133- label . includes ( 'front' ) ||
134- label . includes ( 'selfie' ) ) {
125+ // Categorize cameras with more specific filtering
126+ if ( facingMode === 'user' ||
127+ label . includes ( 'front' ) ||
128+ label . includes ( 'selfie' ) ) {
135129 frontCameras . push ( device ) ;
136130 }
137131 else if ( label . includes ( 'ultra' ) ||
138132 label . includes ( 'wide' ) ||
139133 label . includes ( '0.5' ) ) {
140134 ultrawideCameras . push ( device ) ;
141135 }
136+ else if ( facingMode === 'environment' ||
137+ label . includes ( 'back' ) ||
138+ label . includes ( 'rear' ) ||
139+ ( ! label . includes ( 'front' ) && ! label . includes ( 'selfie' ) ) ) {
140+ backCameras . push ( device ) ;
141+ }
142142 } else {
143143 // Fallback: use label-based filtering without stream access
144144 const label = device . label . toLowerCase ( ) ;
145- if ( label . includes ( 'back' ) ||
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' ) ) {
145+ if ( label . includes ( 'front' ) ||
146+ label . includes ( 'selfie' ) ) {
152147 frontCameras . push ( device ) ;
153148 }
154149 else if ( label . includes ( 'ultra' ) ||
155150 label . includes ( 'wide' ) ||
156151 label . includes ( '0.5' ) ) {
157152 ultrawideCameras . push ( device ) ;
158153 }
154+ else if ( label . includes ( 'back' ) ||
155+ label . includes ( 'rear' ) ||
156+ ( ! label . includes ( 'front' ) && ! label . includes ( 'selfie' ) ) ) {
157+ backCameras . push ( device ) ;
158+ }
159159 }
160160 } catch {
161161 // If we can't get capabilities, use label-based filtering
162162 const label = device . label . toLowerCase ( ) ;
163- if ( label . includes ( 'back' ) ||
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' ) ) {
163+ if ( label . includes ( 'front' ) ||
164+ label . includes ( 'selfie' ) ) {
170165 frontCameras . push ( device ) ;
171166 }
172167 else if ( label . includes ( 'ultra' ) ||
173168 label . includes ( 'wide' ) ||
174169 label . includes ( '0.5' ) ) {
175170 ultrawideCameras . push ( device ) ;
176171 }
172+ else {
173+ backCameras . push ( device ) ;
174+ }
177175 }
178176 }
179177
180- // Build filtered array with back camera first, then front, then ultrawide
178+ // Build final camera selection: exactly one back and one front camera
181179 const filtered : MediaDeviceInfo [ ] = [ ] ;
182180
183- // Add back cameras first (prioritize main back camera)
184- if ( backCameras . length > 0 ) {
185- filtered . push ( backCameras [ 0 ] ) ; // Main back camera
181+ // Select the best back camera (prefer ultrawide if available, otherwise first back camera)
182+ let selectedBackCamera : MediaDeviceInfo | null = null ;
183+ if ( ultrawideCameras . length > 0 ) {
184+ // Check if ultrawide is actually a back camera
185+ const ultrawideBackCamera = ultrawideCameras . find ( camera => {
186+ const label = camera . label . toLowerCase ( ) ;
187+ return ! label . includes ( 'front' ) && ! label . includes ( 'selfie' ) ;
188+ } ) ;
189+ if ( ultrawideBackCamera ) {
190+ selectedBackCamera = ultrawideBackCamera ;
191+ }
192+ }
193+
194+ // If no ultrawide back camera, use regular back camera
195+ if ( ! selectedBackCamera && backCameras . length > 0 ) {
196+ selectedBackCamera = backCameras [ 0 ] ;
186197 }
187198
188- // Add front camera second
199+ // Select front camera
200+ let selectedFrontCamera : MediaDeviceInfo | null = null ;
189201 if ( frontCameras . length > 0 ) {
190- filtered . push ( frontCameras [ 0 ] ) ; // Main front camera
202+ selectedFrontCamera = frontCameras [ 0 ] ;
191203 }
192204
193- // Add ultrawide camera third (if available)
194- if ( ultrawideCameras . length > 0 ) {
195- filtered . push ( ultrawideCameras [ 0 ] ) ; // First ultrawide camera
205+ // Add cameras to filtered array (back camera first for default)
206+ if ( selectedBackCamera ) {
207+ filtered . push ( selectedBackCamera ) ;
208+ }
209+ if ( selectedFrontCamera ) {
210+ filtered . push ( selectedFrontCamera ) ;
196211 }
197212
198213 // Mobile device fallback: if no cameras were categorized properly
199- if ( filtered . length === 0 && devices . length >= 2 && ! permissionGranted ) {
200- // On mobile, typically the first device is back camera, second is front
201- filtered . push ( devices [ 0 ] ) ; // Back camera (usually)
202- if ( devices . length > 1 ) {
214+ if ( filtered . length === 0 && devices . length > 0 ) {
215+ if ( devices . length >= 2 ) {
216+ // Assume first is back, second is front
217+ filtered . push ( devices [ 0 ] ) ; // Back camera (usually)
203218 filtered . push ( devices [ 1 ] ) ; // Front camera (usually)
219+ } else {
220+ // Only one camera available
221+ filtered . push ( devices [ 0 ] ) ;
204222 }
205-
206- // Only add one more camera if it might be ultrawide
207- for ( let i = 2 ; i < devices . length ; i ++ ) {
208- const label = devices [ i ] . label . toLowerCase ( ) ;
209- if ( label . includes ( 'ultra' ) || label . includes ( 'wide' ) || label . includes ( '0.5' ) ) {
210- filtered . push ( devices [ i ] ) ;
211- break ; // Only add one additional camera
212- }
213- }
214- }
215-
216- // Final fallback: if no cameras matched our criteria, fall back to first available camera
217- if ( filtered . length === 0 && devices . length > 0 ) {
218- filtered . push ( devices [ 0 ] ) ;
219223 }
220224
221225 return filtered ;
0 commit comments