@@ -24,6 +24,32 @@ class Camera {
2424  } 
2525} 
2626
27+ const  narrowDownFacingMode  =  async  facingMode  =>  { 
28+   // Modern phones often have multipe front/rear cameras. 
29+   // Sometimes special purpose cameras like the wide-angle camera are picked 
30+   // by default. Those are not optimal for scanning QR codes but standard 
31+   // media constraints don't allow us to specify which camera we want exactly. 
32+   // However, explicitly picking the first entry in the list of all videoinput 
33+   // devices for as the default front camera and the last entry as the default 
34+   // rear camera seems to be a workaround. 
35+   const  devices  =  ( await  navigator . mediaDevices . enumerateDevices ( ) ) . filter ( 
36+     ( {  kind } )  =>  kind  ===  "videoinput" 
37+   ) ; 
38+ 
39+   if  ( devices . length  >  2 )  { 
40+     const  frontCamera  =  devices [ 0 ] ; 
41+     const  rearCamera  =  devices [ devices . length  -  1 ] ; 
42+ 
43+     if  ( facingMode  ===  "front" )  { 
44+       return  {  deviceId : {  exact : frontCamera  }  } ; 
45+     }  else  { 
46+       return  {  deviceId : {  exact : rearCamera  }  } ; 
47+     } 
48+   }  else  { 
49+     return  {  facingMode } ; 
50+   } 
51+ } ; 
52+ 
2753const  INSECURE_CONTEXT  =  window . isSecureContext  !==  true ; 
2854
2955const  STREAM_API_NOT_SUPPORTED  =  ! ( 
@@ -34,13 +60,13 @@ const STREAM_API_NOT_SUPPORTED = !(
3460
3561let  streamApiShimApplied  =  false ; 
3662
37- export  default  async  function ( constraints ,   videoEl ,   advancedConstraints )  { 
63+ export  default  async  function ( videoEl ,   {  facingMode ,  torch  } )  { 
3864  // At least in Chrome `navigator.mediaDevices` is undefined when the page is 
3965  // loaded using HTTP rather than HTTPS. Thus `STREAM_API_NOT_SUPPORTED` is 
4066  // initialized with `false` although the API might actually be supported. 
41-   // So although `getUserMedia` already should have a build -in mechanism to 
67+   // So although `getUserMedia` already should have a built -in mechanism to 
4268  // detect insecure context (by throwing `NotAllowedError`), we have to do a 
43-   // manual check before even calling `getUserMedia`. 
69+   // manual check before even calling `getUserMedia`. 
4470  if  ( INSECURE_CONTEXT )  { 
4571    throw  new  InsecureContextError ( ) ; 
4672  } 
@@ -49,11 +75,22 @@ export default async function(constraints, videoEl, advancedConstraints) {
4975    throw  new  StreamApiNotSupportedError ( ) ; 
5076  } 
5177
78+   // This is a brower API only shim. It patches the global window object which 
79+   // is not available during SSR. So we lazily apply this shim at runtime. 
5280  if  ( streamApiShimApplied  ===  false )  { 
5381    adapterFactory ( {  window } ) ; 
5482    streamApiShimApplied  =  true ; 
5583  } 
5684
85+   const  constraints  =  { 
86+     audio : false , 
87+     video : { 
88+       width : {  min : 360 ,  ideal : 640 ,  max : 1920  } , 
89+       height : {  min : 240 ,  ideal : 480 ,  max : 1080  } , 
90+       ...( await  narrowDownFacingMode ( facingMode ) ) 
91+     } 
92+   } ; 
93+ 
5794  const  stream  =  await  navigator . mediaDevices . getUserMedia ( constraints ) ; 
5895
5996  if  ( videoEl . srcObject  !==  undefined )  { 
@@ -70,7 +107,7 @@ export default async function(constraints, videoEl, advancedConstraints) {
70107
71108  await  eventOn ( videoEl ,  "loadeddata" ) ; 
72109
73-   if  ( advancedConstraints . torch )  { 
110+   if  ( torch )  { 
74111    const  [ track ]  =  stream . getVideoTracks ( ) ; 
75112
76113    try  { 
0 commit comments