|  |  | @ -4,7 +4,9 @@ | 
			
		
	
		
			
				
					|  |  |  |       <div class="text-lg text-center font-bold relative"> | 
			
		
	
		
			
				
					|  |  |  |         <h1 id="ViewHeading" class="text-center font-bold"> | 
			
		
	
		
			
				
					|  |  |  |           <span v-if="uploading">Uploading Image…</span> | 
			
		
	
		
			
				
					|  |  |  |           <span v-else-if="blob">{{ crop ? 'Crop Image' : 'Preview Image' }}</span> | 
			
		
	
		
			
				
					|  |  |  |           <span v-else-if="blob">{{ | 
			
		
	
		
			
				
					|  |  |  |             crop ? "Crop Image" : "Preview Image" | 
			
		
	
		
			
				
					|  |  |  |           }}</span> | 
			
		
	
		
			
				
					|  |  |  |           <span v-else-if="showCameraPreview">Upload Image</span> | 
			
		
	
		
			
				
					|  |  |  |           <span v-else>Add Photo</span> | 
			
		
	
		
			
				
					|  |  |  |         </h1> | 
			
		
	
	
		
			
				
					|  |  | @ -119,7 +121,9 @@ | 
			
		
	
		
			
				
					|  |  |  |                   playsinline | 
			
		
	
		
			
				
					|  |  |  |                   muted | 
			
		
	
		
			
				
					|  |  |  |                 ></video> | 
			
		
	
		
			
				
					|  |  |  |                 <div class="absolute bottom-4 inset-x-0 flex items-center justify-center gap-4"> | 
			
		
	
		
			
				
					|  |  |  |                 <div | 
			
		
	
		
			
				
					|  |  |  |                   class="absolute bottom-4 inset-x-0 flex items-center justify-center gap-4" | 
			
		
	
		
			
				
					|  |  |  |                 > | 
			
		
	
		
			
				
					|  |  |  |                   <button | 
			
		
	
		
			
				
					|  |  |  |                     class="bg-white text-slate-800 p-3 rounded-full text-2xl leading-none" | 
			
		
	
		
			
				
					|  |  |  |                     @click="capturePhoto" | 
			
		
	
	
		
			
				
					|  |  | @ -278,9 +282,9 @@ const inputImageFileNameRef = ref<Blob>(); | 
			
		
	
		
			
				
					|  |  |  |     }, | 
			
		
	
		
			
				
					|  |  |  |     defaultCameraMode: { | 
			
		
	
		
			
				
					|  |  |  |       type: String, | 
			
		
	
		
			
				
					|  |  |  |       default: 'environment', | 
			
		
	
		
			
				
					|  |  |  |       validator: (value: string) => ['environment', 'user'].includes(value) | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |       default: "environment", | 
			
		
	
		
			
				
					|  |  |  |       validator: (value: string) => ["environment", "user"].includes(value), | 
			
		
	
		
			
				
					|  |  |  |     }, | 
			
		
	
		
			
				
					|  |  |  |   }, | 
			
		
	
		
			
				
					|  |  |  | }) | 
			
		
	
		
			
				
					|  |  |  | export default class ImageMethodDialog extends Vue { | 
			
		
	
	
		
			
				
					|  |  | @ -323,7 +327,7 @@ export default class ImageMethodDialog extends Vue { | 
			
		
	
		
			
				
					|  |  |  |   private cameraStream: MediaStream | null = null; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   /** Current camera facing mode */ | 
			
		
	
		
			
				
					|  |  |  |   private currentFacingMode: 'environment' | 'user' = 'environment'; | 
			
		
	
		
			
				
					|  |  |  |   private currentFacingMode: "environment" | "user" = "environment"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   private platformService = PlatformServiceFactory.getInstance(); | 
			
		
	
		
			
				
					|  |  |  |   URL = window.URL || window.webkitURL; | 
			
		
	
	
		
			
				
					|  |  | @ -391,7 +395,7 @@ export default class ImageMethodDialog extends Vue { | 
			
		
	
		
			
				
					|  |  |  |     this.crop = !!crop; | 
			
		
	
		
			
				
					|  |  |  |     this.imageCallback = setImageFn; | 
			
		
	
		
			
				
					|  |  |  |     this.visible = true; | 
			
		
	
		
			
				
					|  |  |  |     this.currentFacingMode = this.defaultCameraMode as 'environment' | 'user'; | 
			
		
	
		
			
				
					|  |  |  |     this.currentFacingMode = this.defaultCameraMode as "environment" | "user"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Start camera preview immediately | 
			
		
	
		
			
				
					|  |  |  |     logger.debug("Starting camera preview from open()"); | 
			
		
	
	
		
			
				
					|  |  | @ -465,7 +469,10 @@ export default class ImageMethodDialog extends Vue { | 
			
		
	
		
			
				
					|  |  |  |     logger.debug("Current showCameraPreview state:", this.showCameraPreview); | 
			
		
	
		
			
				
					|  |  |  |     logger.debug("Platform capabilities:", this.platformCapabilities); | 
			
		
	
		
			
				
					|  |  |  |     logger.debug("MediaDevices available:", !!navigator.mediaDevices); | 
			
		
	
		
			
				
					|  |  |  |     logger.debug("getUserMedia available:", !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)); | 
			
		
	
		
			
				
					|  |  |  |     logger.debug( | 
			
		
	
		
			
				
					|  |  |  |       "getUserMedia available:", | 
			
		
	
		
			
				
					|  |  |  |       !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia), | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     try { | 
			
		
	
		
			
				
					|  |  |  |       this.cameraState = "initializing"; | 
			
		
	
	
		
			
				
					|  |  | @ -492,13 +499,16 @@ export default class ImageMethodDialog extends Vue { | 
			
		
	
		
			
				
					|  |  |  |         videoElement.srcObject = stream; | 
			
		
	
		
			
				
					|  |  |  |         await new Promise((resolve) => { | 
			
		
	
		
			
				
					|  |  |  |           videoElement.onloadedmetadata = () => { | 
			
		
	
		
			
				
					|  |  |  |             videoElement.play().then(() => { | 
			
		
	
		
			
				
					|  |  |  |               logger.debug("Video element started playing"); | 
			
		
	
		
			
				
					|  |  |  |               resolve(true); | 
			
		
	
		
			
				
					|  |  |  |             }).catch(error => { | 
			
		
	
		
			
				
					|  |  |  |               logger.error("Error playing video:", error); | 
			
		
	
		
			
				
					|  |  |  |               throw error; | 
			
		
	
		
			
				
					|  |  |  |             }); | 
			
		
	
		
			
				
					|  |  |  |             videoElement | 
			
		
	
		
			
				
					|  |  |  |               .play() | 
			
		
	
		
			
				
					|  |  |  |               .then(() => { | 
			
		
	
		
			
				
					|  |  |  |                 logger.debug("Video element started playing"); | 
			
		
	
		
			
				
					|  |  |  |                 resolve(true); | 
			
		
	
		
			
				
					|  |  |  |               }) | 
			
		
	
		
			
				
					|  |  |  |               .catch((error) => { | 
			
		
	
		
			
				
					|  |  |  |                 logger.error("Error playing video:", error); | 
			
		
	
		
			
				
					|  |  |  |                 throw error; | 
			
		
	
		
			
				
					|  |  |  |               }); | 
			
		
	
		
			
				
					|  |  |  |           }; | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |       } else { | 
			
		
	
	
		
			
				
					|  |  | @ -510,17 +520,16 @@ export default class ImageMethodDialog extends Vue { | 
			
		
	
		
			
				
					|  |  |  |       let errorMessage = | 
			
		
	
		
			
				
					|  |  |  |         error instanceof Error ? error.message : "Failed to access camera"; | 
			
		
	
		
			
				
					|  |  |  |       if ( | 
			
		
	
		
			
				
					|  |  |  |         error instanceof Error && ( | 
			
		
	
		
			
				
					|  |  |  |         error.name === "NotReadableError" || | 
			
		
	
		
			
				
					|  |  |  |         error.name === "TrackStartError" | 
			
		
	
		
			
				
					|  |  |  |       )) { | 
			
		
	
		
			
				
					|  |  |  |         error instanceof Error && | 
			
		
	
		
			
				
					|  |  |  |         (error.name === "NotReadableError" || error.name === "TrackStartError") | 
			
		
	
		
			
				
					|  |  |  |       ) { | 
			
		
	
		
			
				
					|  |  |  |         errorMessage = | 
			
		
	
		
			
				
					|  |  |  |           "Camera is in use by another application. Please close any other apps or browser tabs using the camera and try again."; | 
			
		
	
		
			
				
					|  |  |  |       } else if ( | 
			
		
	
		
			
				
					|  |  |  |         error instanceof Error && ( | 
			
		
	
		
			
				
					|  |  |  |         error.name === "NotAllowedError" || | 
			
		
	
		
			
				
					|  |  |  |         error.name === "PermissionDeniedError" | 
			
		
	
		
			
				
					|  |  |  |       )) { | 
			
		
	
		
			
				
					|  |  |  |         error instanceof Error && | 
			
		
	
		
			
				
					|  |  |  |         (error.name === "NotAllowedError" || | 
			
		
	
		
			
				
					|  |  |  |           error.name === "PermissionDeniedError") | 
			
		
	
		
			
				
					|  |  |  |       ) { | 
			
		
	
		
			
				
					|  |  |  |         errorMessage = | 
			
		
	
		
			
				
					|  |  |  |           "Camera access was denied. Please allow camera access in your browser settings."; | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
	
		
			
				
					|  |  | @ -590,11 +599,12 @@ export default class ImageMethodDialog extends Vue { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   async rotateCamera() { | 
			
		
	
		
			
				
					|  |  |  |     // Toggle between front and back cameras | 
			
		
	
		
			
				
					|  |  |  |     this.currentFacingMode = this.currentFacingMode === 'environment' ? 'user' : 'environment'; | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |     this.currentFacingMode = | 
			
		
	
		
			
				
					|  |  |  |       this.currentFacingMode === "environment" ? "user" : "environment"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Stop current stream | 
			
		
	
		
			
				
					|  |  |  |     if (this.cameraStream) { | 
			
		
	
		
			
				
					|  |  |  |       this.cameraStream.getTracks().forEach(track => track.stop()); | 
			
		
	
		
			
				
					|  |  |  |       this.cameraStream.getTracks().forEach((track) => track.stop()); | 
			
		
	
		
			
				
					|  |  |  |       this.cameraStream = null; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | 
 |