@ -13,7 +13,7 @@ 
			
		
	
		
			
				
					      >  
			
		
	
		
			
				
					        < div >  
			
		
	
		
			
				
					          < h3  class = "text-lg font-medium text-gray-900" > Scan  QR  Code < / h3 >  
			
		
	
		
			
				
					          < span  class = "text-xs text-gray-500" > v1 .1 .0  build  00000  < / span >  
			
		
	
		
			
				
					          < span  class = "text-xs text-gray-500" > v1 .1 .0 < / span >  
			
		
	
		
			
				
					        < / div >  
			
		
	
		
			
				
					        < button  
			
		
	
		
			
				
					          class = "text-gray-400 hover:text-gray-500"  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -67,8 +67,7 @@ 
			
		
	
		
			
				
					                < path  
			
		
	
		
			
				
					                  class = "opacity-75"  
			
		
	
		
			
				
					                  fill = "currentColor"  
			
		
	
		
			
				
					                  d = " M4  12 a8  8  0  018 - 8 V0C5 .373  0  0  5.373  0  12 h4zm2  5.291 A7 .962  7.962  0  014  12 H0c0   
			
		
	
		
			
				
					    3.042  1.135  5.824  3  7.938 l3 - 2.647 z "  
			
		
	
		
			
				
					                  d = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"  
			
		
	
		
			
				
					                > < / path >  
			
		
	
		
			
				
					              < / svg >  
			
		
	
		
			
				
					              < span > { {  initializationStatus  } } < / span >  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -138,8 +137,7 @@ 
			
		
	
		
			
				
					                stroke - linecap = "round"  
			
		
	
		
			
				
					                stroke - linejoin = "round"  
			
		
	
		
			
				
					                stroke - width = "2"  
			
		
	
		
			
				
					                d = " M3  9 a2  2  0  012 - 2 h .93 a2  2  0  001.664 - .89 l .812 - 1.22 A2  2  0  0110.07  4 h3 .86 a2  2  0   
			
		
	
		
			
				
					        011.664 .89 l .812  1.22 A2  2  0  0018.07  7 H19a2  2  0  012  2 v9a2  2  0  01 - 2  2 H5a2  2  0  01 - 2 - 2 V9z "  
			
		
	
		
			
				
					                d = "M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"  
			
		
	
		
			
				
					              / >  
			
		
	
		
			
				
					              < path  
			
		
	
		
			
				
					                stroke - linecap = "round"  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -164,6 +162,19 @@ 
			
		
	
		
			
				
					        < / div >  
			
		
	
		
			
				
					      < / div >  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      <!--  Error  Banner  -- >  
			
		
	
		
			
				
					      < div  v-if ="error" class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4" role="alert" >  
			
		
	
		
			
				
					        < strong  class = "font-bold" > Camera  Error : < / strong >  
			
		
	
		
			
				
					        < span  class = "block sm:inline" > { {  error  } } < / span >  
			
		
	
		
			
				
					        < ul  class = "mt-2 text-sm text-red-600 list-disc list-inside" >  
			
		
	
		
			
				
					          < li  v-if ="error.includes('No camera found')" > Check  if  your  device  has  a  camera  and  it  is  enabled. < / li >  
			
		
	
		
			
				
					          < li  v-if ="error.includes('denied')" > Allow  camera  access  in  your  browser  settings  and  reload  the  page. < / li >  
			
		
	
		
			
				
					          < li  v-if ="error.includes('in use')" > Close  other  applications  that  may  be  using  the  camera. < / li >  
			
		
	
		
			
				
					          < li  v-if ="error.includes('HTTPS')" > Ensure  you  are  using  a  secure  ( HTTPS )  connection. < / li >  
			
		
	
		
			
				
					          < li  v-if ="!error.includes('No camera found') && !error.includes('denied') && !error.includes('in use') && !error.includes('HTTPS')" > Try  refreshing  the  page  or  using  a  different  browser / device. < / li >  
			
		
	
		
			
				
					        < / ul >  
			
		
	
		
			
				
					      < / div >  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      <!--  Footer  -- >  
			
		
	
		
			
				
					      < div  class = "p-4 border-t border-gray-200" >  
			
		
	
		
			
				
					        < div  class = "flex flex-col space-y-4" >  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -197,14 +208,6 @@ 
			
		
	
		
			
				
					          < / div >  
			
		
	
		
			
				
					        < / div >  
			
		
	
		
			
				
					      < / div >  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      < div  v-if ="debugMessage" class="bg-yellow-200 text-black p-2 m-2 rounded" >  
			
		
	
		
			
				
					        { {  debugMessage  } }  
			
		
	
		
			
				
					      < / div >  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      < div  class = "bg-red-200 text-black p-2 m-2 rounded" >  
			
		
	
		
			
				
					        DEBUG  PANEL :  If  you  see  this ,  the  template  is  updating .  
			
		
	
		
			
				
					      < / div >  
			
		
	
		
			
				
					    < / div >  
			
		
	
		
			
				
					  < / div >  
			
		
	
		
			
				
					< / template >  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -259,7 +262,6 @@ export default class QRScannerDialog extends Vue { 
			
		
	
		
			
				
					  preferredCamera :  "user"  |  "environment"  =  "environment" ;  
			
		
	
		
			
				
					  initializationStatus  =  "Checking camera access..." ;  
			
		
	
		
			
				
					  cameraStatus  =  "Initializing" ;  
			
		
	
		
			
				
					  debugMessage  =  "" ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					  created ( )  {  
			
		
	
		
			
				
					    logger . log ( "QRScannerDialog platform detection:" ,  {  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -282,45 +284,105 @@ export default class QRScannerDialog extends Vue { 
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					  }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					  async  onInit ( promise :  Promise < void > )  {  
			
		
	
		
			
				
					    alert ( "onInit called" ) ;  
			
		
	
		
			
				
					    this . debugMessage  =  "onInit called" ;  
			
		
	
		
			
				
					    let  timeoutHit  =  false ;  
			
		
	
		
			
				
					    const  timeout  =  setTimeout ( ( )  =>  {  
			
		
	
		
			
				
					      timeoutHit  =  true ;  
			
		
	
		
			
				
					      this . isInitializing  =  false ;  
			
		
	
		
			
				
					      this . cameraStatus  =  "Ready (timeout fallback)" ;  
			
		
	
		
			
				
					      this . initializationStatus  =  "Camera ready (fallback)" ;  
			
		
	
		
			
				
					      alert ( "Timeout fallback triggered" ) ;  
			
		
	
		
			
				
					      this . debugMessage  =  "Timeout fallback triggered" ;  
			
		
	
		
			
				
					    } ,  4000 ) ;  
			
		
	
		
			
				
					  async  onInit ( promise :  Promise < void > ) :  Promise < void >  {  
			
		
	
		
			
				
					    if  ( this . isNativePlatform )  {  
			
		
	
		
			
				
					      logger . log ( "Closing QR dialog on native platform" ) ;  
			
		
	
		
			
				
					      this . $nextTick ( ( )  =>  this . close ( ) ) ;  
			
		
	
		
			
				
					      return ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    this . isInitializing  =  true ;  
			
		
	
		
			
				
					    this . error  =  null ;  
			
		
	
		
			
				
					    this . initializationStatus  =  "Checking camera access..." ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    try  {  
			
		
	
		
			
				
					      await  promise ;  
			
		
	
		
			
				
					      if  ( ! timeoutHit )  {  
			
		
	
		
			
				
					        clearTimeout ( timeout ) ;  
			
		
	
		
			
				
					        this . isInitializing  =  false ;  
			
		
	
		
			
				
					        this . cameraStatus  =  "Ready" ;  
			
		
	
		
			
				
					        alert ( "Promise resolved before timeout" ) ;  
			
		
	
		
			
				
					        this . debugMessage  =  "Promise resolved before timeout" ;  
			
		
	
		
			
				
					      / /   F i r s t   c h e c k   i f   m e d i a D e v i c e s   A P I   i s   a v a i l a b l e  
			
		
	
		
			
				
					      if  ( ! navigator . mediaDevices )  {  
			
		
	
		
			
				
					        throw  new  Error (  
			
		
	
		
			
				
					          "Camera API not available. Please ensure you're using HTTPS." ,  
			
		
	
		
			
				
					        ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					    }  catch  ( error )  {  
			
		
	
		
			
				
					      clearTimeout ( timeout ) ;  
			
		
	
		
			
				
					      alert ( "Promise rejected: "  +  ( error  instanceof  Error  ?  error . message  :  error ) ) ;  
			
		
	
		
			
				
					      this . debugMessage  =  "Promise rejected: "  +  ( error  instanceof  Error  ?  error . message  :  error ) ;  
			
		
	
		
			
				
					      if  ( error  instanceof  Error )  {  
			
		
	
		
			
				
					        this . error  =  error . message ;  
			
		
	
		
			
				
					        this . cameraStatus  =  "Error" ;  
			
		
	
		
			
				
					        if  ( this . onError )  {  
			
		
	
		
			
				
					          this . onError ( error ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      / /   C h e c k   f o r   v i d e o   d e v i c e s  
			
		
	
		
			
				
					      const  devices  =  await  navigator . mediaDevices . enumerateDevices ( ) ;  
			
		
	
		
			
				
					      const  videoDevices  =  devices . filter ( device  =>  device . kind  ===  'videoinput' ) ;  
			
		
	
		
			
				
					       
			
		
	
		
			
				
					      if  ( videoDevices . length  ===  0 )  {  
			
		
	
		
			
				
					        throw  new  Error ( "No camera found on this device" ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      logger . log ( "Starting QR scanner initialization..." ,  {  
			
		
	
		
			
				
					        mediaDevices :  ! ! navigator . mediaDevices ,  
			
		
	
		
			
				
					        getUserMedia :  ! ! ( navigator . mediaDevices  &&  navigator . mediaDevices . getUserMedia ) ,  
			
		
	
		
			
				
					        videoDevices :  videoDevices . length ,  
			
		
	
		
			
				
					        constraints :  {  
			
		
	
		
			
				
					          video :  {  
			
		
	
		
			
				
					          facingMode :  this . preferredCamera ,  
			
		
	
		
			
				
					            width :  {  ideal :  1280  } ,  
			
		
	
		
			
				
					            height :  {  ideal :  720  }  
			
		
	
		
			
				
					          }  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					        logger . error ( "Error initializing QR scanner:" ,  {  
			
		
	
		
			
				
					          error :  error . message ,  
			
		
	
		
			
				
					          stack :  error . stack ,  
			
		
	
		
			
				
					      } ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      / /   E x p l i c i t l y   r e q u e s t   c a m e r a   p e r m i s s i o n   f i r s t  
			
		
	
		
			
				
					      this . initializationStatus  =  "Requesting camera permission..." ;  
			
		
	
		
			
				
					      try  {  
			
		
	
		
			
				
					        const  stream  =  await  navigator . mediaDevices . getUserMedia ( {  
			
		
	
		
			
				
					          video :  {  
			
		
	
		
			
				
					            facingMode :  this . preferredCamera ,  
			
		
	
		
			
				
					            width :  {  ideal :  1280  } ,  
			
		
	
		
			
				
					            height :  {  ideal :  720  }  
			
		
	
		
			
				
					          }  
			
		
	
		
			
				
					        } ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        / /   S t o p   t h e   t e s t   s t r e a m   i m m e d i a t e l y  
			
		
	
		
			
				
					        stream . getTracks ( ) . forEach ( ( track )  =>  track . stop ( ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        this . initializationStatus  =  "Camera permission granted..." ;  
			
		
	
		
			
				
					        logger . log ( "Camera permission granted" ) ;  
			
		
	
		
			
				
					      }  catch  ( permissionError )  {  
			
		
	
		
			
				
					        const  error  =  permissionError  as  Error ;  
			
		
	
		
			
				
					        logger . error ( "Camera permission error:" ,  {  
			
		
	
		
			
				
					          name :  error . name ,  
			
		
	
		
			
				
					          type :  error . constructor . name ,  
			
		
	
		
			
				
					          messag e:  error . messag e,  
			
		
	
		
			
				
					        } ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        if  ( error . name  ===  "NotAllowedError"  ||  error . name  ===  "PermissionDeniedError" )  {  
			
		
	
		
			
				
					          throw  new  Error (  
			
		
	
		
			
				
					            "Camera access denied. Please grant camera permission and try again." ,  
			
		
	
		
			
				
					          ) ;  
			
		
	
		
			
				
					        }  else  if  ( error . name  ===  "NotFoundError"  ||  error . name  ===  "DevicesNotFoundError" )  {  
			
		
	
		
			
				
					          throw  new  Error (  
			
		
	
		
			
				
					            "No camera found. Please ensure your device has a camera." ,  
			
		
	
		
			
				
					          ) ;  
			
		
	
		
			
				
					        }  else  if  ( error . name  ===  "NotReadableError"  ||  error . name  ===  "TrackStartError" )  {  
			
		
	
		
			
				
					          throw  new  Error ( "Camera is in use by another application." ) ;  
			
		
	
		
			
				
					        }  else  {  
			
		
	
		
			
				
					          throw  new  Error ( ` Camera error:  ${ error . message } ` ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      / /   N o w   i n i t i a l i z e   t h e   Q R   s c a n n e r  
			
		
	
		
			
				
					      this . initializationStatus  =  "Starting QR scanner..." ;  
			
		
	
		
			
				
					      logger . log ( "Initializing QR scanner..." ) ;  
			
		
	
		
			
				
					      await  promise ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      this . isInitializing  =  false ;  
			
		
	
		
			
				
					      this . cameraStatus  =  "Ready" ;  
			
		
	
		
			
				
					      logger . log ( "QR scanner initialized successfully" ) ;  
			
		
	
		
			
				
					    }  catch  ( error )  {  
			
		
	
		
			
				
					      const  wrappedError  =  error  instanceof  Error  ?  error  :  new  Error ( String ( error ) ) ;  
			
		
	
		
			
				
					      this . error  =  wrappedError . message ;  
			
		
	
		
			
				
					      this . cameraStatus  =  "Error" ;  
			
		
	
		
			
				
					      if  ( this . onError )  {  
			
		
	
		
			
				
					        this . onError ( wrappedError ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					      logger . error ( "Error initializing QR scanner:" ,  {  
			
		
	
		
			
				
					        error :  wrappedError . message ,  
			
		
	
		
			
				
					        stack :  wrappedError . stack ,  
			
		
	
		
			
				
					        name :  wrappedError . name ,  
			
		
	
		
			
				
					        type :  wrappedError . constructor . name ,  
			
		
	
		
			
				
					      } ) ;  
			
		
	
		
			
				
					    }  finally  {  
			
		
	
		
			
				
					      this . isInitializing  =  false ;  
			
		
	
		
			
				
					    }  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -353,8 +415,8 @@ export default class QRScannerDialog extends Vue { 
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					    } ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    / /   H a n d l e   b o t h   p r o m i s e   a n d   n o n - p r o m i s e   r e s u l t s  
			
		
	
		
			
				
					    if  ( result  &&  typeof  result . then  ===  "function" )  {  
			
		
	
		
			
				
					    / /   U s e   i n s t a n c e o f   P r o m i s e   f o r   t y p e   n a r r o w i n g  
			
		
	
		
			
				
					    if  ( result  instanceof  Promise )  {  
			
		
	
		
			
				
					      result  
			
		
	
		
			
				
					        . then ( processResult )  
			
		
	
		
			
				
					        . catch ( ( error :  Error )  =>  this . handleError ( error ) )