+
Camera Error:
{{ error }}
- - Check if your device has a camera and it is enabled.
- - Allow camera access in your browser settings and reload the page.
- - Close other applications that may be using the camera.
- - Ensure you are using a secure (HTTPS) connection.
- - Try refreshing the page or using a different browser/device.
+ -
+ Check if your device has a camera and it is enabled.
+
+ -
+ Allow camera access in your browser settings and reload the page.
+
+ -
+ Close other applications that may be using the camera.
+
+ -
+ Ensure you are using a secure (HTTPS) connection.
+
+ -
+ Try refreshing the page or using a different browser/device.
+
@@ -305,23 +328,27 @@ export default class QRScannerDialog extends Vue {
// Check for video devices
const devices = await navigator.mediaDevices.enumerateDevices();
- const videoDevices = devices.filter(device => device.kind === 'videoinput');
-
+ 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),
+ getUserMedia: !!(
+ navigator.mediaDevices && navigator.mediaDevices.getUserMedia
+ ),
videoDevices: videoDevices.length,
constraints: {
video: {
- facingMode: this.preferredCamera,
+ facingMode: this.preferredCamera,
width: { ideal: 1280 },
- height: { ideal: 720 }
- }
- }
+ height: { ideal: 720 },
+ },
+ },
});
// Explicitly request camera permission first
@@ -331,8 +358,8 @@ export default class QRScannerDialog extends Vue {
video: {
facingMode: this.preferredCamera,
width: { ideal: 1280 },
- height: { ideal: 720 }
- }
+ height: { ideal: 720 },
+ },
});
// Stop the test stream immediately
@@ -347,15 +374,24 @@ export default class QRScannerDialog extends Vue {
message: error.message,
});
- if (error.name === "NotAllowedError" || error.name === "PermissionDeniedError") {
+ 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") {
+ } 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") {
+ } 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}`);
@@ -371,7 +407,8 @@ export default class QRScannerDialog extends Vue {
this.cameraStatus = "Ready";
logger.log("QR scanner initialized successfully");
} catch (error) {
- const wrappedError = error instanceof Error ? error : new Error(String(error));
+ const wrappedError =
+ error instanceof Error ? error : new Error(String(error));
this.error = wrappedError.message;
this.cameraStatus = "Error";
if (this.onError) {
diff --git a/src/services/QRScanner/WebDialogQRScanner.ts b/src/services/QRScanner/WebDialogQRScanner.ts
index 37ae65fb..ac7dfd3e 100644
--- a/src/services/QRScanner/WebDialogQRScanner.ts
+++ b/src/services/QRScanner/WebDialogQRScanner.ts
@@ -30,40 +30,54 @@ export class WebDialogQRScanner implements QRScannerService {
try {
// First check if we have any video devices
const devices = await navigator.mediaDevices.enumerateDevices();
- const videoDevices = devices.filter(device => device.kind === 'videoinput');
-
+ const videoDevices = devices.filter(
+ (device) => device.kind === "videoinput",
+ );
+
if (videoDevices.length === 0) {
- logger.error('No video devices found');
- throw new Error('No camera found on this device');
+ logger.error("No video devices found");
+ throw new Error("No camera found on this device");
}
// Try to get a stream with specific constraints
const stream = await navigator.mediaDevices.getUserMedia({
video: {
- facingMode: 'environment',
+ facingMode: "environment",
width: { ideal: 1280 },
- height: { ideal: 720 }
- }
+ height: { ideal: 720 },
+ },
});
-
+
// Stop the test stream immediately
- stream.getTracks().forEach(track => track.stop());
+ stream.getTracks().forEach((track) => track.stop());
return true;
} catch (error) {
- const wrappedError = error instanceof Error ? error : new Error(String(error));
- logger.error('Error requesting camera permissions:', {
+ const wrappedError =
+ error instanceof Error ? error : new Error(String(error));
+ logger.error("Error requesting camera permissions:", {
error: wrappedError.message,
stack: wrappedError.stack,
- name: wrappedError.name
+ name: wrappedError.name,
});
// Provide more specific error messages
- if (wrappedError.name === 'NotFoundError' || wrappedError.name === 'DevicesNotFoundError') {
- throw new Error('No camera found on this device');
- } else if (wrappedError.name === 'NotAllowedError' || wrappedError.name === 'PermissionDeniedError') {
- throw new Error('Camera access denied. Please grant camera permission and try again');
- } else if (wrappedError.name === 'NotReadableError' || wrappedError.name === 'TrackStartError') {
- throw new Error('Camera is in use by another application');
+ if (
+ wrappedError.name === "NotFoundError" ||
+ wrappedError.name === "DevicesNotFoundError"
+ ) {
+ throw new Error("No camera found on this device");
+ } else if (
+ wrappedError.name === "NotAllowedError" ||
+ wrappedError.name === "PermissionDeniedError"
+ ) {
+ throw new Error(
+ "Camera access denied. Please grant camera permission and try again",
+ );
+ } else if (
+ wrappedError.name === "NotReadableError" ||
+ wrappedError.name === "TrackStartError"
+ ) {
+ throw new Error("Camera is in use by another application");
} else {
throw new Error(`Camera error: ${wrappedError.message}`);
}
@@ -72,32 +86,34 @@ export class WebDialogQRScanner implements QRScannerService {
async isSupported(): Promise
{
try {
- // Check for secure context first
- if (!window.isSecureContext) {
- logger.warn('Camera access requires HTTPS (secure context)');
+ // Check for secure context first
+ if (!window.isSecureContext) {
+ logger.warn("Camera access requires HTTPS (secure context)");
return false;
}
// Check for camera API support
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
- logger.warn('Camera API not supported in this browser');
+ logger.warn("Camera API not supported in this browser");
return false;
}
// Check if we have any video devices
const devices = await navigator.mediaDevices.enumerateDevices();
- const hasVideoDevices = devices.some(device => device.kind === 'videoinput');
-
+ const hasVideoDevices = devices.some(
+ (device) => device.kind === "videoinput",
+ );
+
if (!hasVideoDevices) {
- logger.warn('No video devices found');
+ logger.warn("No video devices found");
return false;
}
return true;
} catch (error) {
- logger.error('Error checking camera support:', {
+ logger.error("Error checking camera support:", {
error: error instanceof Error ? error.message : String(error),
- stack: error instanceof Error ? error.stack : undefined
+ stack: error instanceof Error ? error.stack : undefined,
});
return false;
}