Skip to content

feat: let apps plug a barcode scanner into form fields - #161

Merged
christian2denker merged 3 commits into
mainfrom
feat/barcode-scanner-configuration
Sep 13, 2026
Merged

christian2denker merged 3 commits into
mainfrom
feat/barcode-scanner-configuration

Conversation

@christian2denker

Copy link
Copy Markdown
Contributor

Warum

Ein Barcode- bzw. QR-Scanner im Formular, ohne allen Nutzern des Pakets eine Scanner-Abhängigkeit aufzuzwingen.

Dazu kam heraus: FormFieldProperties.enableBarcodeScanner wird längst aus dem Backend geparst, aber kein Widget hat den Haken je ausgewertet. Was im Web-Frontend konfiguriert wird, verpuffte in Flutter.

Der Ansatz

Ein Scanner-Plugin im Paket hieße native Kamera-Abhängigkeiten und ein NSCameraUsageDescription für jede App, die apptive_grid_form nutzt — ob sie scannt oder nicht. Deshalb definiert das Paket das Loch und die App füllt es, genau wie beim Places-Key:

ApptiveGrid(
  options: ApptiveGridOptions(
    formWidgetConfigurations: [
      BarcodeScannerConfiguration(
        scan: (context) => Navigator.of(context).push<String>(...),
        buttonTooltip: 'Barcode scannen',
      ),
    ],
  ),
  child: ...,
)

Keine neue Dependency. Ohne Konfiguration erscheint nirgends ein Button; für Apps, die das nicht wollen, ändert sich nichts.

Wo der Button erscheint

Feld Bedingung Beim Scan
Text Scanner konfiguriert und enableBarcodeScanner gesetzt Wert landet im Feld
Cross-Reference (einfach und multi) Scanner konfiguriert Picker sucht danach und wählt die Zeile direkt aus, wenn genau eine passt

Cross-Reference wartet bewusst nicht auf enableBarcodeScanner: der Haken ist eine Textfeld-Einstellung, die das Backend dort nie setzt.

Der gescannte Wert läuft über einen ValueNotifier ins Auswahl-Grid, damit es einen Scan von Tippen unterscheiden kann. Die Auto-Auswahl greift nur, solange der Filter noch den gescannten Text hält — tippt jemand weiter, bleibt die Auswahl beim Nutzer.

Der Tooltip liegt in der Konfiguration

Nicht in ApptiveGridTranslation: die Übersetzungen werden von tool/update_translations.sh aus POEditor generiert. Ein lokal ergänzter String verschwände beim nächsten Lauf — und weil die Basisklasse abstrakt ist, wäre das ein Compile-Fehler, kein fehlender Text. Die App bringt das Wort mit, sie bringt ja auch den Scanner.

Auswirkung auf Tests von Consumern

Der Picker liest jetzt beim Bauen die ApptiveGridOptions, um zu sehen, ob ein Scanner da ist. Gegen einen nackten Mock von ApptiveGridClient wirft das:

type 'Null' is not a subtype of type 'ApptiveGridOptions'

Das betraf 88 Tests in diesem Paket. Statt sie einzeln zu flicken trägt MockApptiveGridClient in test/common.dart jetzt ein echtes options-Feld mit Default. Wer den Client in eigenen Widget-Tests mockt und ein Cross-Ref-Feld rendert, braucht dasselbe — steht als NOTE im CHANGELOG. ApptiveTeams ist nicht betroffen (mockt den Client, rendert aber kein Formular im Test).

Testing

  • 7 neue Tests in test/barcode_scanner_test.dart: beide Verweigerungsfälle, Befüllen des Textfelds, deaktivierter Zustand, Auto-Auswahl im Picker und explizit „Cross-Ref wartet nicht auf den Haken"
  • flutter test: 352/352
  • melos run lint:all: SUCCESS
  • flutter pub publish --dry-run: 0 Warnings

🤖 Generated with Claude Code

christian2denker and others added 2 commits September 13, 2026 09:48
`FormFieldProperties.enableBarcodeScanner` was parsed from the backend
but no Widget ever acted on it, so a field configured for scanning in
the web app did nothing in Flutter.

Shipping a scanner in the package would mean native camera dependencies
and a camera usage description for every app using `apptive_grid_form`,
scanning or not. So the package defines the hole and the app fills it:
`BarcodeScannerConfiguration` carries a `scan` callback and goes into
`ApptiveGridOptions.formWidgetConfigurations`, the same way the Places
API key already does. A scan button appears only where both sides agree
— the app provides a scanner and the field asks for one — so nothing
changes for apps that pass no configuration.

Text fields put the scanned value into the field. Cross reference fields
(single and multi, which share the picker) put it into the picker's
search; when the query comes back with exactly one row, that row is
selected right away rather than leaving a second tap to the user. The
value is handed to the picker through a ValueNotifier so the selection
grid can tell a scan apart from typing, and a scan is only acted on
while the filter still holds the scanned text.

The button's tooltip is part of the configuration rather than
`ApptiveGridTranslation`: those translations are generated from POEditor
by tool/update_translations.sh, so a string added locally would be
dropped by the next run and break the build against the abstract base.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
enableBarcodeScanner is a text field setting; the backend never sets it
on a cross reference field, so gating the picker's scan button on it
meant the button never appeared there. The condition now differs by
field: a text field still needs the flag, a cross reference field shows
the button whenever the app configured a scanner. With that the field's
FormFieldProperties are no longer needed in either cross reference
Widget, so the plumbing goes away again.

Reading the options while building the picker turns out to throw against
a bare mocked ApptiveGridClient, which answers `null` where the type
says it cannot. That is what every cross reference test in this package
did, so MockApptiveGridClient carries real options now instead of
stubbing the getter. Consumers mocking the client in widget tests that
render a cross reference field need the same.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the p:form Changes to apptive_grid_form label Sep 13, 2026
The package enforces 100% coverage and CI found three lines short: the
configuration's toString, and the branch that re-runs the query when a
scan matches the text already in the filter. Both are reachable — the
latter whenever someone types a code and then scans the same one, where
without it the button would appear to do nothing — so they get tests
rather than a coverage ignore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@christian2denker
christian2denker merged commit 6fb1d36 into main Sep 13, 2026
6 checks passed
@christian2denker
christian2denker deleted the feat/barcode-scanner-configuration branch September 13, 2026 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p:form Changes to apptive_grid_form

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant