feat: let apps plug a barcode scanner into form fields - #161
Merged
Merged
Conversation
`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>
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Warum
Ein Barcode- bzw. QR-Scanner im Formular, ohne allen Nutzern des Pakets eine Scanner-Abhängigkeit aufzuzwingen.
Dazu kam heraus:
FormFieldProperties.enableBarcodeScannerwird 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
NSCameraUsageDescriptionfür jede App, dieapptive_grid_formnutzt — ob sie scannt oder nicht. Deshalb definiert das Paket das Loch und die App füllt es, genau wie beim Places-Key:Keine neue Dependency. Ohne Konfiguration erscheint nirgends ein Button; für Apps, die das nicht wollen, ändert sich nichts.
Wo der Button erscheint
enableBarcodeScannergesetztCross-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
ValueNotifierins 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 vontool/update_translations.shaus 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 nacktenMockvonApptiveGridClientwirft das:Das betraf 88 Tests in diesem Paket. Statt sie einzeln zu flicken trägt
MockApptiveGridClientintest/common.dartjetzt ein echtesoptions-Feld mit Default. Wer den Client in eigenen Widget-Tests mockt und ein Cross-Ref-Feld rendert, braucht dasselbe — steht alsNOTEim CHANGELOG. ApptiveTeams ist nicht betroffen (mockt den Client, rendert aber kein Formular im Test).Testing
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/352melos run lint:all: SUCCESSflutter pub publish --dry-run: 0 Warnings🤖 Generated with Claude Code