import jpeg from 'jpeg-js'; import jsQR from 'jsqr'; /** * Reads a QR code from a small JPEG snapshot (base64), entirely in JS. Used by * F-Droid builds, which leave out Google's ML Kit scanner. Returns the code's * text, or null if there isn't one. */ export function decodeQrFromJpeg(base64: string): string | null { const bytes = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)); const image = jpeg.decode(bytes, { useTArray: true, formatAsRGBA: true, maxResolutionInMP: 4 }); const code = jsQR(new Uint8ClampedArray(image.data.buffer, image.data.byteOffset, image.data.length), image.width, image.height, { inversionAttempts: 'dontInvert', }); return code?.data ?? null; } /** The smallest snapshot size that still reads a QR code held at arm's length. */ export function pickSnapshotSize(sizes: string[]): string | undefined { const parsed = sizes .map((s) => ({ s, w: Number(s.split('x')[0]), h: Number(s.split('x')[1]) })) .filter((p) => p.w > 0 && p.h > 0) .sort((a, b) => a.w * a.h - b.w * b.h); return (parsed.find((p) => Math.min(p.w, p.h) >= 480) ?? parsed.at(-1))?.s; }