defmodule MobScanner do
@moduledoc """
QR code / barcode scanner — a Mob plugin (extracted from mob core in
Wave 3).
Opens a full-screen camera preview. When a code is detected the view
dismisses automatically and the result is delivered to `handle_info`:
handle_info({:scan, :result, %{type: :qr, value: "https://..."}}, socket)
handle_info({:scan, :cancelled}, socket)
iOS additionally delivers `{:scan, :not_available}` when no camera input
can be opened (core parity, ios/mob_nif.m:2957).
**Requires the mob_camera plugin for the `:camera` permission.** The
`:camera` runtime-permission capability (its registry handler on iOS and
the `MobPermissionProvider` mapping on Android) is owned by mob_camera —
activate mob_camera alongside this plugin and request `:camera` via
`Mob.Permissions.request/2` before calling `scan/2`. mob_camera's manifest
also carries the iOS `NSCameraUsageDescription` plist key.
iOS: `AVCaptureMetadataOutput`. Android: `CameraX` + ML Kit
`BarcodeScanning` in a plugin-owned full-screen Activity
(`io.mob.scanner.MobScannerActivity`) — the host AndroidManifest must
declare it (see `host_requirements` in `priv/mob_plugin.exs`).
"""
@type format ::
:qr
| :ean13
| :ean8
| :code128
| :code39
| :upca
| :upce
| :pdf417
| :aztec
| :data_matrix
@doc """
Open the barcode scanner.
Options:
- `formats: [format]` — list of barcode formats to detect (default `[:qr]`)
Core-parity note: both native sides currently ignore the formats list
(iOS hardcodes its `metadataObjectTypes`, ios/mob_nif.m:2966-2971; the
Android activity scans all ML Kit formats) — it is encoded and passed
through so honoring it later is a non-breaking change.
"""
@spec scan(Mob.Socket.t(), keyword()) :: Mob.Socket.t()
def scan(socket, opts \\ []) do
formats = Keyword.get(opts, :formats, [:qr]) |> Enum.map(&Atom.to_string/1)
formats_json = :json.encode(formats)
:mob_scanner_nif.scanner_scan(formats_json)
socket
end
end