feat(labels): print seed labels with QR from an inventory selection

Add multi-select to the inventory and a "Print labels" flow that renders a
PDF sheet of labels (small stickers or large cards), each carrying the seed's
common name, variety, scientific name, year/origin and a tanemaki://seed QR
that holds the seed's data offline (future scan-to-import).

- SeedLabelCodec: compact, versioned tanemaki://seed URI (encode/decode)
- LabelSheetService: pure-Dart PDF grid (pdf + barcode + DejaVu), RTL-aware
- VarietyRepository.labelRows: one row per lot, locale-picked common name
- InventoryCubit selection mode; contextual app bar + label print sheet
- i18n en/es/pt (printLabels.*)

Tests: codec, PDF service (both formats + RTL), labelRows, selection cubit,
inventory widget selection.
This commit is contained in:
vjrj 2026-07-10 19:14:04 +02:00
parent 432acded29
commit efb369eb81
19 changed files with 1465 additions and 116 deletions

View file

@ -24,6 +24,7 @@ import '../services/file_service.dart';
import '../services/ocr/label_text_extractor.dart';
import '../services/ocr/ocr_language.dart';
import '../services/ocr/tesseract_label_extractor.dart';
import '../services/label_sheet_service.dart';
import '../services/onboarding_store.dart';
import '../services/recovery_sheet_service.dart';
import '../services/share_catalog_service.dart';
@ -104,6 +105,9 @@ Future<void> configureDependencies() async {
)
..registerSingleton<RecoverySheetService>(
RecoverySheetService(files: fileService),
)
..registerSingleton<LabelSheetService>(
LabelSheetService(files: fileService),
);
// Automatic silent backups need real file storage; the web build has none, so