@ -72,18 +72,18 @@ export class WebPlatformService implements PlatformService { 
			
		
	
		
		
			
				
					  }   }  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					  / * *   / * *  
			
		
	
		
		
			
				
					
					   *  Opens  a  file  input  dialog  configured  for  camera  capture .    *  Opens  the  device  camera  for  photo  capture  on  desktop  browsers  using  getUserMedia .  
			
				
				
			
		
	
		
		
			
				
					
					   *  Creates  a  temporary  file  input  element  to  access  the  device  camera .    *  On  mobile  browsers ,  uses  file  input  with  capture  attribute .  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					   *  Falls  back  to  file  input  if  getUserMedia  is  not  available  or  fails .  
			
		
	
		
		
			
				
					   *    *  
			
		
	
		
		
			
				
					   *  @returns  Promise  resolving  to  the  captured  image  data    *  @returns  Promise  resolving  to  the  captured  image  data  
			
		
	
		
		
			
				
					   *  @throws  Error  if  image  capture  fails  or  no  image  is  selected  
			
		
	
		
		
			
				
					   *  
			
		
	
		
		
			
				
					   *  @remarks  
			
		
	
		
		
			
				
					   *  Uses  the  'capture'  attribute  to  prefer  the  device  camera .  
			
		
	
		
		
			
				
					   *  Falls  back  to  file  selection  if  camera  is  not  available .  
			
		
	
		
		
			
				
					   *  Processes  the  captured  image  to  ensure  consistent  format .  
			
		
	
		
		
			
				
					   * /    * /  
			
		
	
		
		
			
				
					  async  takePicture ( ) :  Promise < ImageResult >  {   async  takePicture ( ) :  Promise < ImageResult >  {  
			
		
	
		
		
			
				
					    const  isMobile  =  /iPhone|iPad|iPod|Android/i . test ( navigator . userAgent ) ;  
			
		
	
		
		
			
				
					    const  hasGetUserMedia  =  ! ! ( navigator . mediaDevices  &&  navigator . mediaDevices . getUserMedia ) ;  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					    // If on mobile, use file input with capture attribute (existing behavior)
  
			
		
	
		
		
			
				
					    if  ( isMobile  ||  ! hasGetUserMedia )  {  
			
		
	
		
		
			
				
					      return  new  Promise ( ( resolve ,  reject )  = >  {       return  new  Promise ( ( resolve ,  reject )  = >  {  
			
		
	
		
		
			
				
					        const  input  =  document . createElement ( "input" ) ;         const  input  =  document . createElement ( "input" ) ;  
			
		
	
		
		
			
				
					        input . type  =  "file" ;         input . type  =  "file" ;  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -112,6 +112,111 @@ export class WebPlatformService implements PlatformService { 
			
		
	
		
		
			
				
					      } ) ;       } ) ;  
			
		
	
		
		
			
				
					    }     }  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					    // Desktop: Use getUserMedia for webcam capture
  
			
		
	
		
		
			
				
					    return  new  Promise ( async  ( resolve ,  reject )  = >  {  
			
		
	
		
		
			
				
					      let  stream : MediaStream  |  null  =  null ;  
			
		
	
		
		
			
				
					      let  video : HTMLVideoElement  |  null  =  null ;  
			
		
	
		
		
			
				
					      let  captureButton : HTMLButtonElement  |  null  =  null ;  
			
		
	
		
		
			
				
					      let  overlay : HTMLDivElement  |  null  =  null ;  
			
		
	
		
		
			
				
					      let  cleanup  =  ( )  = >  {  
			
		
	
		
		
			
				
					        if  ( stream )  {  
			
		
	
		
		
			
				
					          stream . getTracks ( ) . forEach ( ( track )  = >  track . stop ( ) ) ;  
			
		
	
		
		
			
				
					        }  
			
		
	
		
		
			
				
					        if  ( video  &&  video . parentNode )  video . parentNode . removeChild ( video ) ;  
			
		
	
		
		
			
				
					        if  ( captureButton  &&  captureButton . parentNode )  captureButton . parentNode . removeChild ( captureButton ) ;  
			
		
	
		
		
			
				
					        if  ( overlay  &&  overlay . parentNode )  overlay . parentNode . removeChild ( overlay ) ;  
			
		
	
		
		
			
				
					      } ;  
			
		
	
		
		
			
				
					      try  {  
			
		
	
		
		
			
				
					        stream  =  await  navigator . mediaDevices . getUserMedia ( {  video :  {  facingMode :  "user"  }  } ) ;  
			
		
	
		
		
			
				
					        // Create overlay for video and button
  
			
		
	
		
		
			
				
					        overlay  =  document . createElement ( "div" ) ;  
			
		
	
		
		
			
				
					        overlay . style . position  =  "fixed" ;  
			
		
	
		
		
			
				
					        overlay . style . top  =  "0" ;  
			
		
	
		
		
			
				
					        overlay . style . left  =  "0" ;  
			
		
	
		
		
			
				
					        overlay . style . width  =  "100vw" ;  
			
		
	
		
		
			
				
					        overlay . style . height  =  "100vh" ;  
			
		
	
		
		
			
				
					        overlay . style . background  =  "rgba(0,0,0,0.8)" ;  
			
		
	
		
		
			
				
					        overlay . style . display  =  "flex" ;  
			
		
	
		
		
			
				
					        overlay . style . flexDirection  =  "column" ;  
			
		
	
		
		
			
				
					        overlay . style . justifyContent  =  "center" ;  
			
		
	
		
		
			
				
					        overlay . style . alignItems  =  "center" ;  
			
		
	
		
		
			
				
					        overlay . style . zIndex  =  "9999" ;  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					        video  =  document . createElement ( "video" ) ;  
			
		
	
		
		
			
				
					        video . autoplay  =  true ;  
			
		
	
		
		
			
				
					        video . playsInline  =  true ;  
			
		
	
		
		
			
				
					        video . style . maxWidth  =  "90vw" ;  
			
		
	
		
		
			
				
					        video . style . maxHeight  =  "70vh" ;  
			
		
	
		
		
			
				
					        video . srcObject  =  stream ;  
			
		
	
		
		
			
				
					        overlay . appendChild ( video ) ;  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					        captureButton  =  document . createElement ( "button" ) ;  
			
		
	
		
		
			
				
					        captureButton . textContent  =  "Capture Photo" ;  
			
		
	
		
		
			
				
					        captureButton . style . marginTop  =  "2rem" ;  
			
		
	
		
		
			
				
					        captureButton . style . padding  =  "1rem 2rem" ;  
			
		
	
		
		
			
				
					        captureButton . style . fontSize  =  "1.2rem" ;  
			
		
	
		
		
			
				
					        captureButton . style . background  =  "#2563eb" ;  
			
		
	
		
		
			
				
					        captureButton . style . color  =  "white" ;  
			
		
	
		
		
			
				
					        captureButton . style . border  =  "none" ;  
			
		
	
		
		
			
				
					        captureButton . style . borderRadius  =  "0.5rem" ;  
			
		
	
		
		
			
				
					        captureButton . style . cursor  =  "pointer" ;  
			
		
	
		
		
			
				
					        overlay . appendChild ( captureButton ) ;  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					        document . body . appendChild ( overlay ) ;  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					        captureButton . onclick  =  async  ( )  = >  {  
			
		
	
		
		
			
				
					          try  {  
			
		
	
		
		
			
				
					            // Create a canvas to capture the frame
  
			
		
	
		
		
			
				
					            const  canvas  =  document . createElement ( "canvas" ) ;  
			
		
	
		
		
			
				
					            canvas . width  =  video ! . videoWidth ;  
			
		
	
		
		
			
				
					            canvas . height  =  video ! . videoHeight ;  
			
		
	
		
		
			
				
					            const  ctx  =  canvas . getContext ( "2d" ) ;  
			
		
	
		
		
			
				
					            ctx ? . drawImage ( video ! ,  0 ,  0 ,  canvas . width ,  canvas . height ) ;  
			
		
	
		
		
			
				
					            canvas . toBlob ( ( blob )  = >  {  
			
		
	
		
		
			
				
					              cleanup ( ) ;  
			
		
	
		
		
			
				
					              if  ( blob )  {  
			
		
	
		
		
			
				
					                resolve ( {  
			
		
	
		
		
			
				
					                  blob ,  
			
		
	
		
		
			
				
					                  fileName :  ` photo_ ${ Date . now ( ) } .jpg ` ,  
			
		
	
		
		
			
				
					                } ) ;  
			
		
	
		
		
			
				
					              }  else  {  
			
		
	
		
		
			
				
					                reject ( new  Error ( "Failed to capture image from webcam" ) ) ;  
			
		
	
		
		
			
				
					              }  
			
		
	
		
		
			
				
					            } ,  "image/jpeg" ,  0.95 ) ;  
			
		
	
		
		
			
				
					          }  catch  ( err )  {  
			
		
	
		
		
			
				
					            cleanup ( ) ;  
			
		
	
		
		
			
				
					            reject ( err ) ;  
			
		
	
		
		
			
				
					          }  
			
		
	
		
		
			
				
					        } ;  
			
		
	
		
		
			
				
					      }  catch  ( error )  {  
			
		
	
		
		
			
				
					        cleanup ( ) ;  
			
		
	
		
		
			
				
					        logger . error ( "Error accessing webcam:" ,  error ) ;  
			
		
	
		
		
			
				
					        // Fallback to file input
  
			
		
	
		
		
			
				
					        const  input  =  document . createElement ( "input" ) ;  
			
		
	
		
		
			
				
					        input . type  =  "file" ;  
			
		
	
		
		
			
				
					        input . accept  =  "image/*" ;  
			
		
	
		
		
			
				
					        input . onchange  =  async  ( e )  = >  {  
			
		
	
		
		
			
				
					          const  file  =  ( e . target  as  HTMLInputElement ) . files ? . [ 0 ] ;  
			
		
	
		
		
			
				
					          if  ( file )  {  
			
		
	
		
		
			
				
					            try  {  
			
		
	
		
		
			
				
					              const  blob  =  await  this . processImageFile ( file ) ;  
			
		
	
		
		
			
				
					              resolve ( {  
			
		
	
		
		
			
				
					                blob ,  
			
		
	
		
		
			
				
					                fileName : file.name  ||  "photo.jpg" ,  
			
		
	
		
		
			
				
					              } ) ;  
			
		
	
		
		
			
				
					            }  catch  ( error )  {  
			
		
	
		
		
			
				
					              logger . error ( "Error processing fallback image:" ,  error ) ;  
			
		
	
		
		
			
				
					              reject ( new  Error ( "Failed to process fallback image" ) ) ;  
			
		
	
		
		
			
				
					            }  
			
		
	
		
		
			
				
					          }  else  {  
			
		
	
		
		
			
				
					            reject ( new  Error ( "No image selected" ) ) ;  
			
		
	
		
		
			
				
					          }  
			
		
	
		
		
			
				
					        } ;  
			
		
	
		
		
			
				
					        input . click ( ) ;  
			
		
	
		
		
			
				
					      }  
			
		
	
		
		
			
				
					    } ) ;  
			
		
	
		
		
			
				
					  }  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					  / * *   / * *  
			
		
	
		
		
			
				
					   *  Opens  a  file  input  dialog  for  selecting  an  image  file .    *  Opens  a  file  input  dialog  for  selecting  an  image  file .  
			
		
	
		
		
			
				
					   *  Creates  a  temporary  file  input  element  to  access  local  files .    *  Creates  a  temporary  file  input  element  to  access  local  files .  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -228,4 +333,14 @@ export class WebPlatformService implements PlatformService { 
			
		
	
		
		
			
				
					    // Web platform can handle deep links through URL parameters
     // Web platform can handle deep links through URL parameters
  
			
		
	
		
		
			
				
					    return  Promise . resolve ( ) ;     return  Promise . resolve ( ) ;  
			
		
	
		
		
			
				
					  }   }  
			
		
	
		
		
			
				
					
 
			
		
	
		
		
			
				
					  / * *  
			
		
	
		
		
			
				
					   *  Not  supported  in  web  platform .  
			
		
	
		
		
			
				
					   *  @param  _fileName  -  Unused  fileName  parameter  
			
		
	
		
		
			
				
					   *  @param  _content  -  Unused  content  parameter  
			
		
	
		
		
			
				
					   *  @throws  Error  indicating  file  system  access  is  not  available  
			
		
	
		
		
			
				
					   * /  
			
		
	
		
		
			
				
					  async  writeAndShareFile ( _fileName : string ,  _content : string ) :  Promise < void >  {  
			
		
	
		
		
			
				
					    throw  new  Error ( "File system access not available in web platform" ) ;  
			
		
	
		
		
			
				
					  }  
			
		
	
		
		
			
				
					} }