diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 60aebe4f..17b388b0 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -3,7 +3,7 @@ name: Eatvio App Android Test on: [ pull_request ] env: - flutter_version: "3.35.1" + flutter_version: "3.38.1" java_version: "21.x" flutter_channel: "stable" my_local_cache_dir: "/opt/hostedtoolcache/" @@ -71,7 +71,7 @@ jobs: - name: Install utils for Android SDK run: | apt-get update - apt-get install -y openjdk-11-jdk wget jq clang cmake ninja-build libgtk-3-dev + apt-get install -y openjdk-17-jdk wget jq clang cmake ninja-build libgtk-3-dev - name: Install Android SDK if: steps.cache-sdk.outputs.cache-hit != 'true' diff --git a/android/build/reports/problems/problems-report.html b/android/build/reports/problems/problems-report.html index ce07f9e3..746fadde 100644 --- a/android/build/reports/problems/problems-report.html +++ b/android/build/reports/problems/problems-report.html @@ -650,7 +650,7 @@ code + .copy-button { diff --git a/lib/features/diary/presentation/pages/barcode_scanner_screen.dart b/lib/features/diary/presentation/pages/barcode_scanner_screen.dart new file mode 100644 index 00000000..19994568 --- /dev/null +++ b/lib/features/diary/presentation/pages/barcode_scanner_screen.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; + +class BarcodeScannerScreen extends StatefulWidget { + const BarcodeScannerScreen({super.key}); + + @override + State createState() => _BarcodeScannerScreenState(); +} + +class _BarcodeScannerScreenState extends State { + final MobileScannerController _controller = MobileScannerController(); + String? _detectedBarcode; + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Сканирование штрихкода'), + centerTitle: true, + ), + body: Column( + children: [ + Expanded( + child: MobileScanner( + controller: _controller, + onDetect: (capture) { + final List barcodes = capture.barcodes; + if (barcodes.isEmpty) return; + final rawValue = barcodes.first.rawValue; + if (rawValue == null || rawValue == _detectedBarcode) return; + setState(() { + _detectedBarcode = rawValue; + }); + }, + ), + ), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: const BoxDecoration( + color: Color(0xFFF6F6F6), + borderRadius: BorderRadius.vertical(top: Radius.circular(24)), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + 'Найденный штрихкод', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 8), + Text( + _detectedBarcode ?? 'Наведите камеру на штрихкод', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: _detectedBarcode == null ? Colors.grey : Colors.black, + ), + ), + const SizedBox(height: 16), + if (_detectedBarcode != null) + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pop(_detectedBarcode); + }, + child: const Text('Использовать штрихкод'), + ), + ), + ], + ), + ), + ], + ), + ); + } +} + diff --git a/lib/features/diary/presentation/widgets/add_product_modal.dart b/lib/features/diary/presentation/widgets/add_product_modal.dart index 4b0a3806..9d77249e 100644 --- a/lib/features/diary/presentation/widgets/add_product_modal.dart +++ b/lib/features/diary/presentation/widgets/add_product_modal.dart @@ -5,9 +5,11 @@ import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart'; import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart'; +import 'package:eatvio_app/features/diary/presentation/pages/barcode_scanner_screen.dart'; import 'package:eatvio_app/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart'; import 'package:eatvio_app/features/glossary/models/glossary_model.dart'; import 'package:flutter/material.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; class AddProductModal extends StatefulWidget { final PortionModel? portion; @@ -62,9 +64,25 @@ class _AddProductModalState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - const Text( - 'Добавление блюда', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: Color(0xFF323F4B)), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Добавление блюда', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: Color(0xFF323F4B)), + ), + IconButton( + onPressed: () async { + final barcode = await Navigator.of(context).push(MaterialPageRoute(builder: (context) => const BarcodeScannerScreen())); + if (barcode != null && barcode.isNotEmpty) { + productNameController.text = barcode; + setState(() {}); + } + }, + splashRadius: 20, + icon: const Icon(Symbols.barcode_scanner, color: Color(0xFF323F4B)), + ), + ], ), const SizedBox(height: 16), Row( diff --git a/pubspec.yaml b/pubspec.yaml index 96d5b2b2..7f6f9014 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,6 +79,7 @@ dependencies: markdown: ^7.3.0 flutter_password_generator: ^1.0.3 mobile_scanner: ^7.1.3 + material_symbols_icons: ^4.2874.0 dev_dependencies: build_runner: ^2.7.0