-
Notifications
You must be signed in to change notification settings - Fork 15
feat: Added Barcode generator screen #122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Reviewer's GuideIntroduces a dedicated barcode generator screen integrated into the image editor, leveraging mobile_scanner for live scanning, barcode_widget for preview and generation logic, and updates navigation and platform permissions accordingly. Sequence diagram for barcode scanning and image generationsequenceDiagram
actor User
participant ImageEditor as Image Editor
participant BarcodeScreen as BarcodeScannerScreen
participant Scanner as mobile_scanner
participant BarcodeWidget
participant Navigator
User->ImageEditor: Tap 'Barcode' button
ImageEditor->Navigator: Push BarcodeScannerScreen
Navigator->BarcodeScreen: Show BarcodeScannerScreen
User->BarcodeScreen: Tap 'Scan Barcode'
BarcodeScreen->Scanner: Start scanning
Scanner->BarcodeScreen: Return scanned barcode data
BarcodeScreen->BarcodeWidget: Update preview
User->BarcodeScreen: Tap 'Generate Image'
BarcodeScreen->BarcodeWidget: Render barcode
BarcodeScreen->ImageEditor: Return generated image
Class diagram for BarcodeScannerScreen and related logicclassDiagram
class BarcodeScannerScreen {
+int width
+int height
}
BarcodeScannerScreen <|-- _BarcodeScannerScreenState
class _BarcodeScannerScreenState {
-GlobalKey _barcodeKey
-TextEditingController _textController
-String _barcodeData
-bool _hasError
-Barcode _selectedBarcode
-bool _showScanner
-MobileScannerController? _scannerController
+void _handleBarcode(BarcodeCapture)
+void _startScanning()
+void _stopScanning()
+Barcode _getBarcodeType(BarcodeFormat?)
+Future<void> _generateBarcodeImage()
+Widget _buildFormatSelector()
+Widget _buildBarcodePreview()
+Widget _buildScannerView()
+Widget build(BuildContext)
}
class MobileScannerController
class Barcode
class BarcodeCapture
class BarcodeWidget
class TextEditingController
class GlobalKey
BarcodeScannerScreen o-- _BarcodeScannerScreenState
_BarcodeScannerScreenState o-- MobileScannerController
_BarcodeScannerScreenState o-- Barcode
_BarcodeScannerScreenState o-- BarcodeWidget
_BarcodeScannerScreenState o-- TextEditingController
_BarcodeScannerScreenState o-- GlobalKey
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @Vishveshwara - I've reviewed your changes - here's some feedback:
- Refactor the large BarcodeScannerScreen into smaller widgets or components (e.g. separate scanner view, format selector, and preview) to improve readability and maintainability.
- Extract the barcode format mapping into a single shared map or helper to avoid duplicating logic in both _getBarcodeType and _buildFormatSelector.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Refactor the large BarcodeScannerScreen into smaller widgets or components (e.g. separate scanner view, format selector, and preview) to improve readability and maintainability.
- Extract the barcode format mapping into a single shared map or helper to avoid duplicating logic in both _getBarcodeType and _buildFormatSelector.
## Individual Comments
### Comment 1
<location> `lib/view/barcode_scanner_screen.dart:201` </location>
<code_context>
+ }
+
+ Widget _buildBarcodePreview() {
+ if (_barcodeData.isEmpty) {
+ return Container(
+ width: 240,
+ height: 120,
</code_context>
<issue_to_address>
Empty barcode data disables format selection and image generation.
Consider enabling format selection even when no barcode data is entered, so users can choose a format before providing data.
Suggested implementation:
```
Widget _buildBarcodePreview() {
if (_barcodeData.isEmpty) {
return Column(
children: [
_buildFormatSelector(), // Always show format selector
const SizedBox(height: 12),
Container(
width: 240,
height: 120,
decoration: BoxDecoration(
color: Colors.grey[200],
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Text(
'Enter or scan barcode data',
style: TextStyle(color: Colors.grey),
),
),
),
],
);
```
If `_buildFormatSelector()` was previously only shown when barcode data was present, you should also ensure that in the "else" branch of `_buildBarcodePreview` (when `_barcodeData` is not empty), the format selector is still shown above the preview. If `_buildFormatSelector()` is not already implemented, you will need to implement it to provide the format selection UI.
</issue_to_address>
### Comment 2
<location> `lib/view/barcode_scanner_screen.dart:221` </location>
<code_context>
+
+ return BarcodeWidget(
+ errorBuilder: (context, error) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ setState(() {
+ _hasError = true;
+ });
</code_context>
<issue_to_address>
Calling setState in errorBuilder may cause unnecessary rebuilds.
Consider handling error state outside the errorBuilder to prevent repeated setState calls and potential performance issues.
</issue_to_address>
### Comment 3
<location> `lib/view/barcode_scanner_screen.dart:138` </location>
<code_context>
+ }
+
+ Widget _buildFormatSelector() {
+ final Map<String, Barcode> availableFormats = {
+ 'QR Code': Barcode.qrCode(),
+ 'Data Matrix': Barcode.dataMatrix(),
+ 'Aztec': Barcode.aztec(),
+ 'PDF417': Barcode.pdf417(),
+ 'Code 128': Barcode.code128(),
+ 'Code 93': Barcode.code93(),
+ 'Code 39': Barcode.code39(),
+ 'Codabar': Barcode.codabar(),
+ 'EAN-13': Barcode.ean13(),
+ 'EAN-8': Barcode.ean8(),
+ 'EAN-5': Barcode.ean5(),
+ 'EAN-2': Barcode.ean2(),
+ 'GS1 128': Barcode.gs128(),
+ 'ISBN': Barcode.isbn(),
+ 'ITF': Barcode.itf(),
+ 'ITF-16': Barcode.itf16(),
+ 'ITF-14': Barcode.itf14(),
+ 'RM4SCC': Barcode.rm4scc(),
+ 'Telepen': Barcode.telepen(),
+ 'UPC-A': Barcode.upcA(),
+ 'UPC-E': Barcode.upcE(),
+ };
+
</code_context>
<issue_to_address>
Some barcode formats in the selector may not be supported by the scanner.
Some formats in availableFormats, such as ISBN, GS1 128, and Telepen, may not be supported by mobile_scanner or device hardware. Please filter out unsupported formats or clearly indicate which ones are unavailable.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
Widget _buildFormatSelector() {
+ final Map<String, Barcode> availableFormats = {
+ 'QR Code': Barcode.qrCode(),
+ 'Data Matrix': Barcode.dataMatrix(),
+ 'Aztec': Barcode.aztec(),
+ 'PDF417': Barcode.pdf417(),
+ 'Code 128': Barcode.code128(),
+ 'Code 93': Barcode.code93(),
+ 'Code 39': Barcode.code39(),
+ 'Codabar': Barcode.codabar(),
+ 'EAN-13': Barcode.ean13(),
+ 'EAN-8': Barcode.ean8(),
+ 'EAN-5': Barcode.ean5(),
+ 'EAN-2': Barcode.ean2(),
+ 'GS1 128': Barcode.gs128(),
+ 'ISBN': Barcode.isbn(),
+ 'ITF': Barcode.itf(),
+ 'ITF-16': Barcode.itf16(),
+ 'ITF-14': Barcode.itf14(),
+ 'RM4SCC': Barcode.rm4scc(),
+ 'Telepen': Barcode.telepen(),
+ 'UPC-A': Barcode.upcA(),
+ 'UPC-E': Barcode.upcE(),
+ };
=======
Widget _buildFormatSelector() {
+ // Only include formats supported by mobile_scanner and most device hardware.
+ final Map<String, Barcode> availableFormats = {
+ 'QR Code': Barcode.qrCode(),
+ 'Data Matrix': Barcode.dataMatrix(),
+ 'Aztec': Barcode.aztec(),
+ 'PDF417': Barcode.pdf417(),
+ 'Code 128': Barcode.code128(),
+ 'Code 93': Barcode.code93(),
+ 'Code 39': Barcode.code39(),
+ 'Codabar': Barcode.codabar(),
+ 'EAN-13': Barcode.ean13(),
+ 'EAN-8': Barcode.ean8(),
+ 'ITF': Barcode.itf(),
+ 'UPC-A': Barcode.upcA(),
+ 'UPC-E': Barcode.upcE(),
+ // Add more formats here if confirmed supported by mobile_scanner and device hardware.
+ };
>>>>>>> REPLACE
</suggested_fix>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
if (_barcodeData.isEmpty) { | ||
return Container( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Empty barcode data disables format selection and image generation.
Consider enabling format selection even when no barcode data is entered, so users can choose a format before providing data.
Suggested implementation:
Widget _buildBarcodePreview() {
if (_barcodeData.isEmpty) {
return Column(
children: [
_buildFormatSelector(), // Always show format selector
const SizedBox(height: 12),
Container(
width: 240,
height: 120,
decoration: BoxDecoration(
color: Colors.grey[200],
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Text(
'Enter or scan barcode data',
style: TextStyle(color: Colors.grey),
),
),
),
],
);
If _buildFormatSelector()
was previously only shown when barcode data was present, you should also ensure that in the "else" branch of _buildBarcodePreview
(when _barcodeData
is not empty), the format selector is still shown above the preview. If _buildFormatSelector()
is not already implemented, you will need to implement it to provide the format selection UI.
void initState() { | ||
super.initState(); | ||
_textController.addListener(() { | ||
setState(() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (performance): Calling setState in errorBuilder may cause unnecessary rebuilds.
Consider handling error state outside the errorBuilder to prevent repeated setState calls and potential performance issues.
Widget _buildFormatSelector() { | ||
final Map<String, Barcode> availableFormats = { | ||
'QR Code': Barcode.qrCode(), | ||
'Data Matrix': Barcode.dataMatrix(), | ||
'Aztec': Barcode.aztec(), | ||
'PDF417': Barcode.pdf417(), | ||
'Code 128': Barcode.code128(), | ||
'Code 93': Barcode.code93(), | ||
'Code 39': Barcode.code39(), | ||
'Codabar': Barcode.codabar(), | ||
'EAN-13': Barcode.ean13(), | ||
'EAN-8': Barcode.ean8(), | ||
'EAN-5': Barcode.ean5(), | ||
'EAN-2': Barcode.ean2(), | ||
'GS1 128': Barcode.gs128(), | ||
'ISBN': Barcode.isbn(), | ||
'ITF': Barcode.itf(), | ||
'ITF-16': Barcode.itf16(), | ||
'ITF-14': Barcode.itf14(), | ||
'RM4SCC': Barcode.rm4scc(), | ||
'Telepen': Barcode.telepen(), | ||
'UPC-A': Barcode.upcA(), | ||
'UPC-E': Barcode.upcE(), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Some barcode formats in the selector may not be supported by the scanner.
Some formats in availableFormats, such as ISBN, GS1 128, and Telepen, may not be supported by mobile_scanner or device hardware. Please filter out unsupported formats or clearly indicate which ones are unavailable.
Widget _buildFormatSelector() { | |
final Map<String, Barcode> availableFormats = { | |
'QR Code': Barcode.qrCode(), | |
'Data Matrix': Barcode.dataMatrix(), | |
'Aztec': Barcode.aztec(), | |
'PDF417': Barcode.pdf417(), | |
'Code 128': Barcode.code128(), | |
'Code 93': Barcode.code93(), | |
'Code 39': Barcode.code39(), | |
'Codabar': Barcode.codabar(), | |
'EAN-13': Barcode.ean13(), | |
'EAN-8': Barcode.ean8(), | |
'EAN-5': Barcode.ean5(), | |
'EAN-2': Barcode.ean2(), | |
'GS1 128': Barcode.gs128(), | |
'ISBN': Barcode.isbn(), | |
'ITF': Barcode.itf(), | |
'ITF-16': Barcode.itf16(), | |
'ITF-14': Barcode.itf14(), | |
'RM4SCC': Barcode.rm4scc(), | |
'Telepen': Barcode.telepen(), | |
'UPC-A': Barcode.upcA(), | |
'UPC-E': Barcode.upcE(), | |
}; | |
Widget _buildFormatSelector() { | |
+ // Only include formats supported by mobile_scanner and most device hardware. | |
+ final Map<String, Barcode> availableFormats = { | |
+ 'QR Code': Barcode.qrCode(), | |
+ 'Data Matrix': Barcode.dataMatrix(), | |
+ 'Aztec': Barcode.aztec(), | |
+ 'PDF417': Barcode.pdf417(), | |
+ 'Code 128': Barcode.code128(), | |
+ 'Code 93': Barcode.code93(), | |
+ 'Code 39': Barcode.code39(), | |
+ 'Codabar': Barcode.codabar(), | |
+ 'EAN-13': Barcode.ean13(), | |
+ 'EAN-8': Barcode.ean8(), | |
+ 'ITF': Barcode.itf(), | |
+ 'UPC-A': Barcode.upcA(), | |
+ 'UPC-E': Barcode.upcE(), | |
+ // Add more formats here if confirmed supported by mobile_scanner and device hardware. | |
+ }; |
WhatsApp.Video.2025-07-30.at.7.04.22.PM.mp4 |
Build StatusBuild successful. APKs to test: https://github.com/fossasia/magic-epaper-app/actions/runs/16872887988/artifacts/3731890247. |
@Dhruv1797 did you review this? |
screen-20250807-191249.mp4 |
Fixes #98
Utilizes mobile_scanner package for scanning the barcodes in real time and uses the barcode_widget for generating an image.
Summary by Sourcery
Add a new Barcode Scanner and Generator screen to enable real-time scanning and image generation of various barcode formats, integrate it into the image editor menu, and configure required permissions and dependencies.
New Features:
Enhancements:
Build: