diff --git a/example/lib/models/code.dart b/example/lib/models/code.dart index 6b69c43..1224822 100644 --- a/example/lib/models/code.dart +++ b/example/lib/models/code.dart @@ -21,4 +21,6 @@ class Code extends HiveObject { format = result.format; text = result.textString; } + + String get formatName => FlutterZxing.formatName(format ?? 0); } diff --git a/example/lib/models/encode.dart b/example/lib/models/encode.dart index d018974..5c94bbc 100644 --- a/example/lib/models/encode.dart +++ b/example/lib/models/encode.dart @@ -24,11 +24,13 @@ class Encode extends HiveObject { Encode(); - Encode.fromEncodeResult(EncodeResult result) { + Encode.fromEncodeResult(EncodeResult result, Uint8List? bytes) { isValid = result.isValidBool; format = result.format; text = result.textString; - data = result.bytes as Uint8List?; + data = bytes; length = result.length; } + + String get formatName => FlutterZxing.formatName(format ?? 0); } diff --git a/example/lib/pages/barcodes_page.dart b/example/lib/pages/barcodes_page.dart new file mode 100644 index 0000000..b50624e --- /dev/null +++ b/example/lib/pages/barcodes_page.dart @@ -0,0 +1,82 @@ +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_zxing_example/models/models.dart'; +import 'package:flutter_zxing_example/utils/db_service.dart'; +import 'package:flutter_zxing_example/utils/router.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:hive_flutter/hive_flutter.dart'; + +class BarcodesPage extends StatefulWidget { + const BarcodesPage({ + Key? key, + }) : super(key: key); + + @override + State createState() => _BarcodesPageState(); +} + +class _BarcodesPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Barcodes'), + ), + body: _buildResultList(), + floatingActionButton: FloatingActionButton( + child: const Icon(FontAwesomeIcons.plus), + onPressed: () { + Navigator.of(context).pushNamed(AppRoutes.creator); + }, + ), + ); + } + + _buildResultList() { + return ValueListenableBuilder>( + valueListenable: DbService.instance.getEncodes().listenable(), + builder: (context, box, _) { + final results = box.values.toList().cast(); + return results.isEmpty + ? const Center( + child: Text( + 'Tap + to create a Barcode', + style: TextStyle(fontSize: 24), + )) + : ListView.builder( + itemCount: results.length, + itemBuilder: (context, index) { + final result = results[index]; + return ListTile( + leading: Image.memory(result.data ?? Uint8List(0)), + title: Text(result.text ?? ''), + subtitle: Text(result.formatName), + trailing: ButtonBar( + mainAxisSize: MainAxisSize.min, + children: [ + // Copy button + TextButton( + child: const Text('Copy'), + onPressed: () { + Clipboard.setData( + ClipboardData(text: result.text)); + }, + ), + // Remove button + IconButton( + icon: const Icon(Icons.delete, color: Colors.red), + onPressed: () { + DbService.instance.deleteEncode(result); + setState(() {}); + }, + ), + ], + ), + ); + }, + ); + }); + } +} diff --git a/example/lib/pages/creator_page.dart b/example/lib/pages/creator_page.dart index 8f2955f..076b565 100644 --- a/example/lib/pages/creator_page.dart +++ b/example/lib/pages/creator_page.dart @@ -3,6 +3,8 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_zxing/flutter_zxing.dart'; +import 'package:flutter_zxing_example/models/encode.dart'; +import 'package:flutter_zxing_example/utils/db_service.dart'; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; @@ -22,7 +24,7 @@ class _CreatorPageState extends State { bool isAndroid() => Theme.of(context).platform == TargetPlatform.android; // Write result - Uint8List? writeResult; + Encode? encode; @override void initState() { @@ -47,14 +49,14 @@ class _CreatorPageState extends State { child: Column( children: [ ZxingWriterWidget( - onSuccess: (result) { + onSuccess: (result, bytes) { setState(() { - writeResult = result; + encode = Encode.fromEncodeResult(result, bytes); }); }, onError: (error) { setState(() { - writeResult = null; + encode = null; }); ScaffoldMessenger.of(context).hideCurrentSnackBar(); ScaffoldMessenger.of(context).showSnackBar( @@ -70,7 +72,7 @@ class _CreatorPageState extends State { ); }, ), - if (writeResult != null) buildWriteResult(), + if (encode != null) buildWriteResult(), ], ), ), @@ -81,18 +83,34 @@ class _CreatorPageState extends State { return Column( children: [ // Barcode image - Image.memory(writeResult ?? Uint8List(0)), + Image.memory(encode?.data ?? Uint8List(0)), + const SizedBox(height: 20), // Share button - ElevatedButton( - onPressed: () { - // Save image to device - final file = File(tempPath); - file.writeAsBytesSync(writeResult ?? Uint8List(0)); - final path = file.path; - // Share image - Share.shareFiles([path]); - }, - child: const Text('Share'), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: () { + // Save image to device + final file = File(tempPath); + file.writeAsBytesSync(encode?.data ?? Uint8List(0)); + final path = file.path; + // Share image + Share.shareFiles([path]); + }, + child: const Text('Share'), + ), + ElevatedButton( + onPressed: () async { + if (encode != null) { + await DbService.instance.addEncode(encode!); + Navigator.of(context).pop(); + } + }, + child: const Text('Save'), + ), + ], ), ], ); diff --git a/example/lib/pages/history_page.dart b/example/lib/pages/history_page.dart index fe60d67..4e7ca2d 100644 --- a/example/lib/pages/history_page.dart +++ b/example/lib/pages/history_page.dart @@ -41,7 +41,7 @@ class _HistoryPageState extends State { final result = results[index]; return ListTile( title: Text(result.text ?? ''), - subtitle: Text(result.format.toString()), + subtitle: Text(result.formatName), trailing: ButtonBar( mainAxisSize: MainAxisSize.min, children: [ @@ -57,8 +57,8 @@ class _HistoryPageState extends State { IconButton( icon: const Icon(Icons.delete, color: Colors.red), onPressed: () { - // DbService.instance.deleteCode(result); - // setState(() {}); + DbService.instance.deleteCode(result); + setState(() {}); }, ), ], diff --git a/example/lib/pages/home_page.dart b/example/lib/pages/home_page.dart index e70d5a8..62886db 100644 --- a/example/lib/pages/home_page.dart +++ b/example/lib/pages/home_page.dart @@ -1,5 +1,6 @@ import 'package:convex_bottom_bar/convex_bottom_bar.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_zxing_example/pages/barcodes_page.dart'; import 'package:flutter_zxing_example/pages/creator_page.dart'; import 'package:flutter_zxing_example/pages/history_page.dart'; import 'package:flutter_zxing_example/pages/scanner_page.dart'; @@ -16,14 +17,14 @@ class HomePage extends StatefulWidget { class _HomePageState extends State { var selectedIndex = 2; - final creatorPage = const CreatorPage(); + final barcodesPage = const BarcodesPage(); final historyPage = const HistoryPage(); final scannerPage = const ScannerPage(); final helpPage = Container(); final settingsPage = const SettingsPage(); dynamic pages() => [ - creatorPage, + barcodesPage, historyPage, scannerPage, helpPage, diff --git a/example/lib/utils/db_service.dart b/example/lib/utils/db_service.dart index 03a4804..2243acd 100644 --- a/example/lib/utils/db_service.dart +++ b/example/lib/utils/db_service.dart @@ -9,42 +9,53 @@ class DbService { Future initializeApp() async { await Hive.initFlutter(); Hive.registerAdapter(CodeAdapter()); + Hive.registerAdapter(EncodeAdapter()); await Hive.openBox('codes'); await Hive.openBox('encodes'); - - // Hive.box('codes').close(); } Box getCodes() => Hive.box('codes'); Future deleteCodes() async { - var codes = getCodes(); - await codes.deleteAll(codes.keys); + var items = getCodes(); + await items.deleteAll(items.keys); return; } Future addCode(Code value) async { - var codes = getCodes(); - if (!codes.values.contains(value)) { - return codes.add(value); + var items = getCodes(); + if (!items.values.contains(value)) { + return items.add(value); } return; } + Future deleteCode(Code value) async { + var items = getCodes(); + await items.delete(value.key); + return; + } + Box getEncodes() => Hive.box('encodes'); Future deleteEncodes() async { - var encodes = getEncodes(); - await encodes.deleteAll(encodes.keys); + var items = getEncodes(); + await items.deleteAll(items.keys); return; } Future addEncode(Encode value) async { - var encodes = getEncodes(); - if (!encodes.values.contains(value)) { - return encodes.add(value); + var items = getEncodes(); + if (!items.values.contains(value)) { + return items.add(value); } return; } + + Future deleteEncode(Encode value) async { + var items = getEncodes(); + await items.delete(value.key); + return; + } } diff --git a/lib/flutter_zxing.dart b/lib/flutter_zxing.dart index 98ecfd9..d488883 100644 --- a/lib/flutter_zxing.dart +++ b/lib/flutter_zxing.dart @@ -51,6 +51,8 @@ class FlutterZxing { } static int get _logEnabled => logEnabled ? 1 : 0; + + static String formatName(int format) => _formatNames[format] ?? 'Unknown'; } // Getting a library that holds needed symbols @@ -79,44 +81,20 @@ extension CodeExt on CodeResult { bool get isValidBool => isValid == 1; String? get textString => text == nullptr ? null : text.cast().toDartString(); - String get formatString => CodeFormat.formatName(format); + String get formatString => FlutterZxing.formatName(format); } extension EncodeExt on EncodeResult { bool get isValidBool => isValid == 1; String? get textString => text == nullptr ? null : text.cast().toDartString(); - String get formatString => CodeFormat.formatName(format); + String get formatString => FlutterZxing.formatName(format); Uint32List get bytes => data.asTypedList(length); String get errorMessage => error.cast().toDartString(); } extension CodeFormat on Format { - static String formatName(int format) => formatNames[format] ?? 'Unknown'; - String get name => formatNames[this] ?? 'Unknown'; - - static final formatNames = { - Format.None: 'None', - Format.Aztec: 'Aztec', - Format.Codabar: 'CodaBar', - Format.Code39: 'Code39', - Format.Code93: 'Code93', - Format.Code128: 'Code128', - Format.DataBar: 'DataBar', - Format.DataBarExpanded: 'DataBarExpanded', - Format.DataMatrix: 'DataMatrix', - Format.EAN8: 'EAN8', - Format.EAN13: 'EAN13', - Format.ITF: 'ITF', - Format.MaxiCode: 'MaxiCode', - Format.PDF417: 'PDF417', - Format.QRCode: 'QR Code', - Format.UPCA: 'UPCA', - Format.UPCE: 'UPCE', - Format.OneDCodes: 'OneD', - Format.TwoDCodes: 'TwoD', - Format.Any: 'Any', - }; + String get name => _formatNames[this] ?? 'Unknown'; static final writerFormats = [ Format.QRCode, @@ -137,3 +115,26 @@ extension CodeFormat on Format { // Format.MaxiCode, ]; } + +final _formatNames = { + Format.None: 'None', + Format.Aztec: 'Aztec', + Format.Codabar: 'CodaBar', + Format.Code39: 'Code39', + Format.Code93: 'Code93', + Format.Code128: 'Code128', + Format.DataBar: 'DataBar', + Format.DataBarExpanded: 'DataBarExpanded', + Format.DataMatrix: 'DataMatrix', + Format.EAN8: 'EAN8', + Format.EAN13: 'EAN13', + Format.ITF: 'ITF', + Format.MaxiCode: 'MaxiCode', + Format.PDF417: 'PDF417', + Format.QRCode: 'QR Code', + Format.UPCA: 'UPCA', + Format.UPCE: 'UPCE', + Format.OneDCodes: 'OneD', + Format.TwoDCodes: 'TwoD', + Format.Any: 'Any', +}; diff --git a/lib/zxing_writer_widget.dart b/lib/zxing_writer_widget.dart index 991b5fa..1c2ac09 100644 --- a/lib/zxing_writer_widget.dart +++ b/lib/zxing_writer_widget.dart @@ -12,7 +12,7 @@ class ZxingWriterWidget extends StatefulWidget { this.onError, }) : super(key: key); - final Function(Uint8List)? onSuccess; + final Function(EncodeResult, Uint8List)? onSuccess; final Function(String)? onError; @override @@ -48,7 +48,7 @@ class _ZxingWriterWidgetState extends State items: _supportedFormats .map((format) => DropdownMenuItem( value: format, - child: Text(CodeFormat.formatName(format)), + child: Text(FlutterZxing.formatName(format)), )) .toList(), onChanged: (format) { @@ -84,16 +84,16 @@ class _ZxingWriterWidgetState extends State final text = _textController.value.text; const width = 300; const height = 300; - final result = FlutterZxing.encodeBarcode( + var result = FlutterZxing.encodeBarcode( text, width, height, _codeFormat, 5, 0); String? error; if (result.isValidBool) { try { final img = imglib.Image.fromBytes(width, height, result.bytes); - final resultBytes = + final encodedBytes = Uint8List.fromList(imglib.encodeJpg(img)); - widget.onSuccess?.call(resultBytes); + widget.onSuccess?.call(result, encodedBytes); } on Exception catch (e) { error = e.toString(); }