style: improve code formatting and readability

- Format Vue template attributes and event handlers for better readability
- Reorganize component props and event bindings
- Improve error handling and state management in QR scanner
- Add proper aria labels and accessibility attributes
- Refactor camera state handling in WebInlineQRScanner
- Clean up promise handling in WebPlatformService
- Standardize string quotes to double quotes
- Improve component structure and indentation

No functional changes, purely code style and maintainability improvements.
This commit is contained in:
Matt Raymer
2025-05-20 01:15:47 -04:00
parent d6956bb498
commit df8acefeff
7 changed files with 341 additions and 224 deletions

View File

@@ -1,4 +1,10 @@
import { QRScannerService, ScanListener, QRScannerOptions, CameraState, CameraStateListener } from "./types";
import {
QRScannerService,
ScanListener,
QRScannerOptions,
CameraState,
CameraStateListener,
} from "./types";
import { logger } from "@/utils/logger";
import { EventEmitter } from "events";
import jsQR from "jsqr";
@@ -22,7 +28,7 @@ export class WebInlineQRScanner implements QRScannerService {
private readonly FRAME_INTERVAL = 1000 / 15; // ~67ms between frames
private lastFrameTime = 0;
private cameraStateListeners: Set<CameraStateListener> = new Set();
private currentState: CameraState = 'off';
private currentState: CameraState = "off";
private currentStateMessage?: string;
constructor(private options?: QRScannerOptions) {
@@ -49,15 +55,21 @@ export class WebInlineQRScanner implements QRScannerService {
private updateCameraState(state: CameraState, message?: string) {
this.currentState = state;
this.currentStateMessage = message;
this.cameraStateListeners.forEach(listener => {
this.cameraStateListeners.forEach((listener) => {
try {
listener.onStateChange(state, message);
logger.info(`[WebInlineQRScanner:${this.id}] Camera state changed to: ${state}`, {
state,
message,
});
logger.info(
`[WebInlineQRScanner:${this.id}] Camera state changed to: ${state}`,
{
state,
message,
},
);
} catch (error) {
logger.error(`[WebInlineQRScanner:${this.id}] Error in camera state listener:`, error);
logger.error(
`[WebInlineQRScanner:${this.id}] Error in camera state listener:`,
error,
);
}
});
}
@@ -74,7 +86,7 @@ export class WebInlineQRScanner implements QRScannerService {
async checkPermissions(): Promise<boolean> {
try {
this.updateCameraState('initializing', 'Checking camera permissions...');
this.updateCameraState("initializing", "Checking camera permissions...");
logger.error(
`[WebInlineQRScanner:${this.id}] Checking camera permissions...`,
);
@@ -86,7 +98,7 @@ export class WebInlineQRScanner implements QRScannerService {
permissions.state,
);
const granted = permissions.state === "granted";
this.updateCameraState(granted ? 'ready' : 'permission_denied');
this.updateCameraState(granted ? "ready" : "permission_denied");
return granted;
} catch (error) {
logger.error(
@@ -96,14 +108,17 @@ export class WebInlineQRScanner implements QRScannerService {
stack: error instanceof Error ? error.stack : undefined,
},
);
this.updateCameraState('error', 'Error checking camera permissions');
this.updateCameraState("error", "Error checking camera permissions");
return false;
}
}
async requestPermissions(): Promise<boolean> {
try {
this.updateCameraState('initializing', 'Requesting camera permissions...');
this.updateCameraState(
"initializing",
"Requesting camera permissions...",
);
logger.error(
`[WebInlineQRScanner:${this.id}] Requesting camera permissions...`,
);
@@ -141,8 +156,8 @@ export class WebInlineQRScanner implements QRScannerService {
},
});
this.updateCameraState('ready', 'Camera permissions granted');
this.updateCameraState("ready", "Camera permissions granted");
// Stop the test stream immediately
stream.getTracks().forEach((track) => {
logger.error(`[WebInlineQRScanner:${this.id}] Stopping test track:`, {
@@ -154,20 +169,35 @@ export class WebInlineQRScanner implements QRScannerService {
});
return true;
} catch (error) {
const wrappedError = error instanceof Error ? error : new Error(String(error));
const wrappedError =
error instanceof Error ? error : new Error(String(error));
// Update state based on error type
if (wrappedError.name === "NotFoundError" || wrappedError.name === "DevicesNotFoundError") {
this.updateCameraState('not_found', 'No camera found on this device');
if (
wrappedError.name === "NotFoundError" ||
wrappedError.name === "DevicesNotFoundError"
) {
this.updateCameraState("not_found", "No camera found on this device");
throw new Error("No camera found on this device");
} else if (wrappedError.name === "NotAllowedError" || wrappedError.name === "PermissionDeniedError") {
this.updateCameraState('permission_denied', 'Camera access denied');
throw new Error("Camera access denied. Please grant camera permission and try again");
} else if (wrappedError.name === "NotReadableError" || wrappedError.name === "TrackStartError") {
this.updateCameraState('in_use', 'Camera is in use by another application');
} else if (
wrappedError.name === "NotAllowedError" ||
wrappedError.name === "PermissionDeniedError"
) {
this.updateCameraState("permission_denied", "Camera access denied");
throw new Error(
"Camera access denied. Please grant camera permission and try again",
);
} else if (
wrappedError.name === "NotReadableError" ||
wrappedError.name === "TrackStartError"
) {
this.updateCameraState(
"in_use",
"Camera is in use by another application",
);
throw new Error("Camera is in use by another application");
} else {
this.updateCameraState('error', wrappedError.message);
this.updateCameraState("error", wrappedError.message);
throw new Error(`Camera error: ${wrappedError.message}`);
}
}
@@ -406,7 +436,7 @@ export class WebInlineQRScanner implements QRScannerService {
this.isScanning = true;
this.scanAttempts = 0;
this.lastScanTime = Date.now();
this.updateCameraState('initializing', 'Starting camera...');
this.updateCameraState("initializing", "Starting camera...");
logger.error(`[WebInlineQRScanner:${this.id}] Starting scan`);
// Get camera stream
@@ -421,8 +451,8 @@ export class WebInlineQRScanner implements QRScannerService {
},
});
this.updateCameraState('active', 'Camera is active');
this.updateCameraState("active", "Camera is active");
logger.error(`[WebInlineQRScanner:${this.id}] Camera stream obtained:`, {
tracks: this.stream.getTracks().map((t) => ({
kind: t.kind,
@@ -448,15 +478,22 @@ export class WebInlineQRScanner implements QRScannerService {
this.scanQRCode();
} catch (error) {
this.isScanning = false;
const wrappedError = error instanceof Error ? error : new Error(String(error));
const wrappedError =
error instanceof Error ? error : new Error(String(error));
// Update state based on error type
if (wrappedError.name === "NotReadableError" || wrappedError.name === "TrackStartError") {
this.updateCameraState('in_use', 'Camera is in use by another application');
if (
wrappedError.name === "NotReadableError" ||
wrappedError.name === "TrackStartError"
) {
this.updateCameraState(
"in_use",
"Camera is in use by another application",
);
} else {
this.updateCameraState('error', wrappedError.message);
this.updateCameraState("error", wrappedError.message);
}
if (this.scanListener?.onError) {
this.scanListener.onError(wrappedError);
}
@@ -513,8 +550,11 @@ export class WebInlineQRScanner implements QRScannerService {
`[WebInlineQRScanner:${this.id}] Stream stopped event emitted`,
);
} catch (error) {
logger.error(`[WebInlineQRScanner:${this.id}] Error stopping scan:`, error);
this.updateCameraState('error', 'Error stopping camera');
logger.error(
`[WebInlineQRScanner:${this.id}] Error stopping scan:`,
error,
);
this.updateCameraState("error", "Error stopping camera");
throw error;
} finally {
this.isScanning = false;
@@ -557,8 +597,11 @@ export class WebInlineQRScanner implements QRScannerService {
`[WebInlineQRScanner:${this.id}] Cleanup completed successfully`,
);
} catch (error) {
logger.error(`[WebInlineQRScanner:${this.id}] Error during cleanup:`, error);
this.updateCameraState('error', 'Error during cleanup');
logger.error(
`[WebInlineQRScanner:${this.id}] Error during cleanup:`,
error,
);
this.updateCameraState("error", "Error during cleanup");
throw error;
}
}