Skip to content

Releases: nettrash/Scan

v1.8.59

03 May 10:15

Choose a tag to compare

Scan v1.8.59 — Release Notes

It's been a while since 1.1 — here's everything that's landed since.

Now on Mac and Vision Pro

  • Mac (Catalyst). Scan now ships as a native Mac app with the same bundle ID and iCloud library. Use your built-in webcam or a Continuity Camera to scan, and pinch on the trackpad to zoom.
  • Vision Pro. Apple doesn't expose Vision Pro's cameras to third-party apps, so the Scan tab there leads with Choose from Photos / Choose from Files instead of a broken viewfinder. Generate works as on iPad, and your full history syncs in.
  • Same library, every device. iCloud sync now actually replicates — scan on iPhone, see it on Mac and Vision Pro a moment later.

Smarter scanning

  • Pinch to zoom on the live camera, capped at 8× so you don't end up zooming into noise.
  • Centred-frame focus. The recogniser only looks at the area inside the corner brackets, so a stray code at the edge of the frame can't steal a scan from the one you're aiming at.
  • Multi-code disambiguation. When more than one barcode is in frame, you'll see numbered chips on each — tap the one you actually want.
  • Live preview no longer freezes when a result is recognised. The sheet slides up over a still-running camera, with smart de-duplication so the same code doesn't keep re-presenting.
  • Reticle releases when no codes are visible, instead of staying stuck on the last one.

Share to Scan + PDF support

  • Share Extension. Scan now appears in the iOS share sheet. Send it images or PDFs from any app and decode them inline, up to 10 at once.
  • PDFs are decoded end-to-end — every page is rasterised at 2× and run through the recogniser. Works in the Files importer too.

Universal Links

  • Open https://nettrash.me/scan/<payload> links straight into a result sheet with all the usual smart actions and a one-tap Save to History. Great for sharing a code as a plain link.

New payload types

  • Wi-Fi: WPA3 (SAE) and Passpoint (HS20) recognised, with friendly security labels and a heads-up that Passpoint profiles need to be installed manually.
  • Stablecoins: USDC / USDT / DAI tagged automatically across Ethereum (EIP-681 ERC-20 transfers), Tron (TRC-20) and Solana (Solana Pay SPL). Bare Tron addresses (T…) are detected too.
  • Digital identity: DigiD, EUDI Wallet and OpenID4VC login flows recognised, with an explicit warning so a stranger's QR can't quietly log you into their session.
  • Loyalty cards. Save a product barcode as a loyalty card with a merchant tag — pinned to the top of History, instantly findable in search.
  • GS1 Application Identifiers in all three forms (parens, GS1 Digital Link, FNC1).
  • IATA boarding passes (PDF417, RP 1740c) — passenger, PNR, route, flight, seat, sequence.
  • AAMVA driver's licences (PDF417) for US states + Canadian provinces.
  • Magnet links, plus richer URL recognition (WhatsApp, Telegram, Wallet .pkpass, App Store, YouTube, Spotify, Apple Music, Google/Apple Maps).
  • More crypto chains: XRP, Stellar, Cosmos, LNURL, Lightning Address — and bare-address detection for legacy + bech32 Bitcoin, Ethereum, XRP, Stellar, Cosmos, bolt11, LNURL.

Generator

  • Foreground / background colour pickers with a live preview and a WCAG contrast warning when you drop below 3:1.
  • QR error-correction picker (L/M/Q/H), forced to H when a logo is set.
  • Logo embedding with an automatic white "punch" behind it so the finder pattern stays scannable.
  • SVG and PDF exports alongside PNG — true vector output that prints cleanly at any size.
  • Reset to default to get back to plain black-on-white in one tap.
  • Tap-outside / drag-down to dismiss the keyboard, plus a Done toolbar accessory.

History

  • Favourites. Star a scan to pin it to the top, with a Favourites-only filter chip in the toolbar.
  • CSV export of either the visible list (respects search + filters) or everything, RFC 4180-compliant.

Settings (new tab)

  • Haptic on scan (on by default), sound on scan (off by default), continuous scanning mode that saves straight to History and shows an inline banner instead of a sheet.
  • Test feedback button to compare the two.
  • iCloud sync status — see at a glance whether you're signed in, with a pointer to system Settings if not.

What's New sheet

  • A first-launch summary after every version bump, so you see what changed without having to come find these notes.

App Store + housekeeping

v1.1.22

28 Apr 20:58

Choose a tag to compare

Full Changelog: v1.1...v1.1.22

v1.1

28 Apr 17:23

Choose a tag to compare

Full Changelog: v1.0.10...v1.1

v1.0.10

26 Apr 20:50

Choose a tag to compare

Changelog

All notable changes to this project are documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

CFBundleVersion (build number) is the value of CURRENT_PROJECT_VERSION
in the project file and is now auto-incremented by the app target's
build-phase script via agvtool next-version -all.

v1.0.10

Added

App shell

  • Replaced the default Xcode SwiftUI + Core Data template with a real
    three-tab app: Scan, Generate, History.

  • App icon is a real, scannable QR code pointing to
    https://nettrash.me, framed by amber viewfinder corner brackets on a
    navy gradient. Verified pixel-accurate against the canonical encoding.

  • Build number (CFBundleVersion) auto-increments via a scheme
    post-action
    on the Scan shared scheme that runs
    cd "${PROJECT_DIR}" ; agvtool bump after every successful build.
    agvtool bump (alias for next-version -all) rewrites
    CURRENT_PROJECT_VERSION in project.pbxproj directly — no
    build-phase script and so no User Script Sandbox to fight.
    Same mechanism the sibling Geo app uses; ported wholesale.

    Earlier iterations tried two other approaches that didn't survive
    contact with reality: a PBXShellScriptBuildPhase deriving the
    build number from git rev-list --count HEAD (Xcode 14+'s default
    ENABLE_USER_SCRIPT_SANDBOXING = YES blocks the script from
    reading .git/, so it printed "Could not determine git commit
    count" and left the version unchanged); and pure manual bumping
    via Editor → Increase Build Number (worked but easy to forget).
    The post-action approach is sandbox-friendly and runs automatically.

Live camera scanner

  • ScannerScreen + CameraScannerView (UIViewControllerRepresentable
    wrapping AVCaptureSession + AVCaptureMetadataOutput).
  • Symbologies: QR, Aztec, PDF417, Data Matrix, EAN-8, EAN-13, UPC-E,
    Code 39 (and mod-43 checksum), Code 93, Code 128, ITF-14, Interleaved 2
    of 5, Codabar, GS1 DataBar variants where the device supports them.
  • Camera-permission flow with descriptive failure messaging.
  • Torch toggle.
  • Accent-coloured viewfinder corner brackets (no decorative outline —
    scan area is implied by the brackets).
  • Result-debouncing so repeated reads of the same code in quick
    succession don't spam the result sheet.

Image import (still scans)

  • Import from Photo Library (PhotosPicker) and Files
    (fileImporter).
  • ImageDecoder runs VNDetectBarcodesRequest on a background queue;
    surfaces decoded codes through the same result sheet as live scans.
  • Vision-symbology mapping into the app's Symbology enum, including
    microQR / microPDF417 / GS1 DataBar variants.
  • Decoding spinner; pauses the live session while reading.

Smart payload decomposition

ScanPayload is parsed from the decoded string and rendered as
labelled, copyable fields. Recognised:

  • URLs (http / https)
  • Email (mailto: with subject/body params)
  • Phone (tel:)
  • SMS / SMSTO (sms:, smsto:NUMBER:BODY)
  • Wi-Fi (WIFI:T:…;S:…;P:…;H:…;;) with backslash-escape support
  • Geolocation (geo:lat,lon?q=…)
  • vCard 3.0 and MECARD contacts
  • iCalendar VEVENT with RFC-5545 line-folding, UTC / TZID / all-day
    date forms, escape-sequence unescaping, mailto: stripped from organizer
  • One-time-password URIs (otpauth://)
  • EAN-8 / EAN-13 / UPC-E / ITF-14 product codes (driven by
    symbology, not text content)
  • Cryptocurrency wallet URIs:
    • Bitcoin (BIP-21)
    • Ethereum (EIP-681 with @chainId)
    • Litecoin, Bitcoin Cash, Dogecoin, Monero, Cardano, Solana
    • Lightning (BOLT-11)
  • Bank payments:
    • EPC SEPA Payment QR (GiroCode) — line-based, v001 / v002
    • Swiss QR-bill (SPC) — full address-block parsing (S / K),
      creditor + ultimate creditor + ultimate debtor, QRR / SCOR / NON
      reference types
    • Czech SPD (Spayd) — asterisk-delimited SPD*1.0*ACC:…*AM:…*…*;
      surfaces IBAN, amount + currency, recipient, message, due date,
      variable / constant / specific symbols (X-VS / X-KS / X-SS),
      with +-to-space decoding per SPD escaping rules
    • Slovak Pay by Square — recognised heuristically (header prefix
      plus all-base32hex check); decoding requires LZMA which iOS doesn't
      ship, so the result sheet labels the format and offers Copy / Share
      so the raw token can be passed to a banking app
    • Russian unified payment (ST00012 / ST00011) — pipe-separated
      fields with friendly English labels for the well-known keys; Sum
      converted from kopecks to rubles
    • EMVCo Merchant QR — top-level TLV walker plus recursive drilling
      into Tag 62 (Additional Data: Bill number / Mobile number / Store
      label / Reference label / Customer label / Terminal label / Purpose
      of transaction) and Tags 02–51 (Merchant Account Information).
      Recognises 14 known scheme GUIDs and renames the parent row by
      scheme: Pix, PayNow, NETS, PromptPay, CoDi,
      UPI, FPS (Hong Kong), DuitNow (Malaysia), QRIS
      (Indonesia), NAPAS (Vietnam), and friends. Sub-fields render with
      a "↳" marker for individual tap-to-copy. 28-currency ISO 4217
      numeric→alpha mapping; static / dynamic initiation-method labels.
    • Indian UPI (upi://pay) — VPA, payee name, amount + currency
      (defaults INR), note, merchant code, transaction ID, and reference
      URL all surfaced as labelled fields
    • Bezahlcode (German legacy bank:// / bezahlcode://) — full
      field mapping (beneficiary, IBAN, BIC, amount, currency, purpose,
      creditor / mandate IDs)
    • Serbian NBS IPS QR (Prenesi) — K:value | … format with
      PR / PT / PK kind labels, percent-decoded recipient names, validates
      required K / R / V fields
  • Mobile-payment apps (regional URI schemes):
    • Swish (Sweden, swish://payment?data=<base64-JSON>) —
      base64-decoded JSON exposes payee, amount, message, currency
    • Vipps (Norway, vipps://) — phone number, amount, message,
      merchant ID, order text
    • MobilePay (Denmark / Finland, mobilepay://) — phone, amount,
      comment, locked-amount flag
    • Bizum (Spain, bizum://) — phone, amount, concept
    • iDEAL (Netherlands, ideal://) — IBAN, amount, beneficiary,
      description, reference
  • Receipts:
    • Russian FNS retail receipt — Europe/Moscow timestamp parsed to a
      Date, sale / refund / expense / expense-refund classification
    • Serbian SUF fiscal receipt — recognised by suf.purs.gov.rs
      host (exact match or proper subdomain — lookalike domains rejected);
      "Verify Receipt" action opens the official PURS verification page

Smart actions per payload

  • URL → Open in Safari.
  • Email / Phone / SMS → Compose / Call / Send via the right system app.
  • Wi-Fi → Show details, copy password, open Wi-Fi Settings.
  • Location → Open in Maps.
  • ContactAdd to Contacts via CNContactViewController with a
    CNContactViewControllerDelegate coordinator (Done / Cancel dismiss
    the sheet correctly).
  • CalendarAdd to Calendar via EKEventEditViewController,
    using requestWriteOnlyAccessToEvents on iOS 17+ and requestAccess(to:.event)
    on iOS 16. Denial alert directs the user to Settings.
  • Crypto → Open in Wallet (iOS picks an installed wallet via the URI
    scheme).
  • UPI → Open in UPI app (handed off via upi: scheme so iOS picks
    an installed UPI app — PhonePe, GPay, Paytm, BHIM…).
  • Mobile-payment apps (Swish / Vipps / MobilePay / Bizum / iDEAL) →
    Open in via the registered URI scheme.
  • Product code → Look up via web search.
  • Serbian SUF → Verify Receipt (opens PURS site).
  • All payloads → global Copy + Share buttons; per-field tap-to-copy on
    bank / receipt / crypto / Serbian / Czech / UPI / calendar payloads.

Generation

  • New Generate tab in the TabView.
  • Inputs: Text, URL, Contact, Wi-Fi.
  • Symbologies: QR (correction level M), Aztec, PDF417, Code 128.
  • Outputs: Share (system sheet), Save to Photos (uses
    PHPhotoLibrary.requestAuthorization(for: .addOnly) for least
    privilege), Copy (puts both image and encoded string on
    UIPasteboard via setObjects).
  • Composers:
    • vCard 3.0 with CRLF line endings, FN/N split, and proper
      text-value escaping.
    • WIFI: payload with backslash-escaped special chars; password field
      omitted when "None" security is selected.
  • Live preview that re-renders on every keystroke; integer-scaled
    rendering for crisp module edges; multi-line-content warning when
    Code 128 is paired with content that contains newlines.

History

  • ScanRecord Core Data entity (id, value, symbology, timestamp,
    notes) replacing the template's stub Item entity.
  • NSPersistentCloudKitContainer so saved scans sync across the user's
    iCloud devices.
  • Searchable list with relative timestamps and a payload-kind SF Symbol
    per row.
  • Empty state via a ContentUnavailableView (with an iOS 16 fallback).
  • Per-record detail screen with editable notes, smart actions, share,
    delete.

Permissions / Info.plist

  • NSCameraUsageDescription for the live scanner.
  • NSPhotoLibraryAddUsageDescription for Save-to-Photos in the
    generator.
  • NSContactsUsageDescription for Add-to-Contacts.
  • NSCalendarsUsageDescription and NSCalendarsWriteOnlyAccessUsageDescription
    for Add-to-Calendar.
  • All keys also mirrored as INFOPLIST_KEY_* build settings, since the
    project uses GENERATE_INFOPLIST_FILE = YES.

Tests

  • ScanTests covers parser ...
Read more