diff --git a/src/components/tools/QrScanner.vue b/src/components/tools/QrScanner.vue index 5d24e46..30b1628 100644 --- a/src/components/tools/QrScanner.vue +++ b/src/components/tools/QrScanner.vue @@ -8,7 +8,7 @@ const scannedCodes = ref([]) const hasMultipleCameras = ref(false) const isFullscreen = ref(false) const videoAspect = ref(1) -const isFront = computed(() => facingMode.value === 'user') +const isMirrored = ref(false) const wrapperRef = ref(null) const bgCanvas = ref(null) let bgRafId = null @@ -65,31 +65,27 @@ const paintDetections = (codes) => { } const scale = drawWidth / vw - const isMirrored = isFront.value + // Canvas is mirrored via CSS if isMirrored is true, so no manual coordinate mirroring needed - // Styles - const styles = getComputedStyle(document.documentElement) - const accent = styles.getPropertyValue('--primary-accent').trim() || '#00f2fe' + // Styles + const styles = getComputedStyle(document.documentElement) + const accent = styles.getPropertyValue('--primary-accent').trim() || '#00f2fe' - ctx.lineWidth = 4 - ctx.strokeStyle = accent - ctx.fillStyle = accent + ctx.lineWidth = 4 + ctx.strokeStyle = accent + ctx.fillStyle = accent - codes.forEach(code => { - const points = code.cornerPoints - if (!points || points.length < 4) return + codes.forEach(code => { + const points = code.cornerPoints + if (!points || points.length < 4) return - ctx.beginPath() + ctx.beginPath() - const transform = (p) => { - let x = p.x * scale + startX - let y = p.y * scale + startY - - if (isMirrored) { - x = width - x - } - return { x, y } - } + const transform = (p) => { + let x = p.x * scale + startX + let y = p.y * scale + startY + return { x, y } + } const p0 = transform(points[0]) ctx.moveTo(p0.x, p0.y) @@ -203,6 +199,23 @@ const startScan = async () => { stream = await navigator.mediaDevices.getUserMedia(constraints) + // Detect actual facing mode to mirror front camera correctly + const videoTrack = stream.getVideoTracks()[0] + if (videoTrack) { + const settings = videoTrack.getSettings() + if (settings.facingMode) { + isMirrored.value = settings.facingMode === 'user' + } else { + // Fallback: check label for desktop cameras or assume requested mode + const label = videoTrack.label ? videoTrack.label.toLowerCase() : '' + if (label.includes('front') || label.includes('facetime') || label.includes('macbook')) { + isMirrored.value = true + } else { + isMirrored.value = facingMode.value === 'user' + } + } + } + if (videoRef.value) { videoRef.value.srcObject = stream // Wait for metadata to play @@ -464,7 +477,7 @@ const isUrl = (string) => {