- Frame count now shows: scanned / useful (linearly independent) / minimal needed
- Camera zoom via getUserMedia track.applyConstraints when supported
- Software crop fallback with visible dashed-square overlay on video
- Corner markers on scan region for visual feedback
- qr_decode accepts inversionAttempts option for faster GIF decoding
- Preserved attemptBoth for camera scanning (handles glare/reflections)
- Remove CBOR manifest and manifest.ts entirely
- Fixed 18-byte packet header: sessionId, generationIndex, symbolIndex,
packetType, totalGenerations, dataLength, flags, reserved
- Single hardcoded profile: QR V10, ECC M, K=16, R=8, payload=191 bytes
- Add isText flag (bit 0 of flags) for text vs binary routing
- Remove hash computation and profile selection UI
- Update all tests to match new protocol (33 tests passing)
- Fix generateCoefficients arg order bug in complete.test.ts
- Fix createQRGif dimension bug in tests
- Make prod_roundtrip frame loss deterministic
All 33 tests pass. Build succeeds.
The dedup key was `::`, which
caused manifest fragment 0 to collide with systematic symbol 0. The RLNC
decoder then never reached full rank, so generations never solved and the
receiver appeared to hang.
- Add packetType to dedup key so manifest/systematic/coded symbols are unique
- Add completed session flag to ignore late frames after reconstruction
- Prevent trailing progress message from overwriting complete status
- Add frame_decode and prod_roundtrip tests
- Rewrote GIF LZW decoder (gif_parser.ts) — old version produced
wrong pixel indices for larger images (V20 QR frames), causing
all QR decodes to fail after GIF roundtrip
- Added full end-to-end test: encode → QR → GIF → parse GIF →
decode QR → RLNC decode → reconstruct (94 tests passing)
- Added GIF File input mode to receiver for debug/testing
- Fixed receiver stale closure bug (scanning state captured
as false, preventing any frame capture)
- GIF parser handles: LZW, interlaced, local/global palettes,
Graphics Control Extension, disposal methods
- Fix stale closure bug in camera capture loop (scanning state
captured as false, preventing any frame capture)
- Add GIF File input mode to receiver — upload a QR-over-GIF
directly to test the decode pipeline without camera
- Update decode worker to accept imageData or frameData
- Receiver now shows two input modes: Camera and GIF File
The rAF capture loop checked where
was a state variable captured in a stale closure.
The loop was created when scanning=false, so it immediately
exited on every frame and never captured any camera frames.
Fix: use scanningRef (useRef) instead of state for the loop
guard, so the rAF callback always reads the live value.