Files
aiturk-hermes-ide/apps/mobile/src/qr.mjs
T

51 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import qrcode from './vendor/qrcode.mjs'
export function drawQr(canvas, text) {
const qr = qrcode(0, 'M'); qr.addData(text); qr.make()
const count = qr.getModuleCount(), scale = 5, margin = 4
canvas.width = canvas.height = (count + margin * 2) * scale
const ctx = canvas.getContext('2d'); ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = '#000'
for (let y = 0; y < count; y++) for (let x = 0; x < count; x++)
if (qr.isDark(y, x)) ctx.fillRect((x + margin) * scale, (y + margin) * scale, scale, scale)
}
export class InviteScanner {
constructor(video, onCode) { this.video = video; this.onCode = onCode; this.epoch = 0; this.canvas = document.createElement('canvas') }
decode(source, width, height) {
if (!width || !height) return null
const scale = Math.min(1, 1280 / Math.max(width, height))
this.canvas.width = Math.round(width * scale); this.canvas.height = Math.round(height * scale)
const ctx = this.canvas.getContext('2d', { willReadFrequently: true })
ctx.drawImage(source, 0, 0, this.canvas.width, this.canvas.height)
const pixels = ctx.getImageData(0, 0, this.canvas.width, this.canvas.height)
return globalThis.jsQR(pixels.data, pixels.width, pixels.height)?.data
}
async image(file) {
this.stop(); const epoch = this.epoch
if (!file || file.size > 8 * 1024 * 1024) throw new Error('QR resmi en fazla 8 MB olabilir.')
const bitmap = await createImageBitmap(file)
let result
try { result = this.decode(bitmap, bitmap.width, bitmap.height) } finally { bitmap.close() }
if (epoch !== this.epoch) return
if (!result) throw new Error('Resimde QR okunamadı; daha net bir görüntü deneyin.')
await this.onCode(result)
}
async start() {
this.stop(); const epoch = this.epoch
const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio: false })
if (epoch !== this.epoch) { stream.getTracks().forEach(t => t.stop()); return }
this.stream = stream; this.video.srcObject = stream; this.video.hidden = false
try {
await this.video.play()
if (epoch !== this.epoch) return
this.timer = setInterval(() => {
const result = this.decode(this.video, this.video.videoWidth, this.video.videoHeight)
if (result) { this.stop(); void this.onCode(result).catch(error => this.onError?.(error)) }
}, 250)
this.limit = setTimeout(() => this.stop(), 60000)
} catch (error) { this.stop(); throw error }
}
stop() { this.epoch++; clearInterval(this.timer); clearTimeout(this.limit); this.stream?.getTracks().forEach(t => t.stop()); this.stream = null; this.video.srcObject = null; this.video.hidden = true }
}