diff --git a/assets/fonts/OpenSans-Bold.ttf b/assets/fonts/OpenSans-Bold.ttf new file mode 100644 index 0000000..4d8f3e5 Binary files /dev/null and b/assets/fonts/OpenSans-Bold.ttf differ diff --git a/assets/fonts/OpenSans-BoldItalic.ttf b/assets/fonts/OpenSans-BoldItalic.ttf new file mode 100644 index 0000000..eba75d7 Binary files /dev/null and b/assets/fonts/OpenSans-BoldItalic.ttf differ diff --git a/assets/fonts/OpenSans-Italic.ttf b/assets/fonts/OpenSans-Italic.ttf new file mode 100644 index 0000000..b088474 Binary files /dev/null and b/assets/fonts/OpenSans-Italic.ttf differ diff --git a/assets/fonts/OpenSans-Regular.ttf b/assets/fonts/OpenSans-Regular.ttf new file mode 100644 index 0000000..3a29f26 Binary files /dev/null and b/assets/fonts/OpenSans-Regular.ttf differ diff --git a/lib/data/provider/auth_fb.dart b/lib/data/provider/auth_fb.dart index d89e12d..49b5dbb 100644 --- a/lib/data/provider/auth_fb.dart +++ b/lib/data/provider/auth_fb.dart @@ -250,6 +250,7 @@ class AuthFb { StreamSubscription? authListener; Future _start() async { + await authListener?.cancel(); authListener = _fb.authStateChanges().listen((firebaseUser) { if (firebaseUser == null) { controller.add(null); @@ -261,12 +262,8 @@ class AuthFb { } void _stop() { - if (userListener != null) { - userListener!.cancel(); - } - if (authListener != null) { - authListener!.cancel(); - } + userListener?.cancel(); + authListener?.cancel(); } controller = StreamController( diff --git a/lib/helpers/pdf.dart b/lib/helpers/pdf.dart new file mode 100644 index 0000000..20d7159 --- /dev/null +++ b/lib/helpers/pdf.dart @@ -0,0 +1,69 @@ +import 'dart:io'; +import 'package:flutter/services.dart'; +import 'package:open_file/open_file.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pdf/pdf.dart'; +import 'package:pdf/widgets.dart' as pw; + +import '../domain/entities/carton.dart'; + +Future generateCartonPdf(Carton carton) async { + var myTheme = pw.ThemeData.withFont( + base: + pw.Font.ttf(await rootBundle.load("assets/fonts/OpenSans-Regular.ttf")), + bold: pw.Font.ttf(await rootBundle.load("assets/fonts/OpenSans-Bold.ttf")), + italic: + pw.Font.ttf(await rootBundle.load("assets/fonts/OpenSans-Italic.ttf")), + boldItalic: pw.Font.ttf( + await rootBundle.load("assets/fonts/OpenSans-BoldItalic.ttf")), + ); + + final doc = pw.Document( + theme: myTheme, + ); + + PdfPageFormat format = + const PdfPageFormat(PdfPageFormat.inch * 3, PdfPageFormat.inch * 1); + doc.addPage(pw.Page( + pageFormat: format, + build: (pw.Context context) { + return pw.Padding( + padding: const pw.EdgeInsets.all(5), + child: pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.start, + crossAxisAlignment: pw.CrossAxisAlignment.center, + children: [ + pw.BarcodeWidget( + width: 50, + height: 50, + color: PdfColor.fromHex("#000000"), + barcode: pw.Barcode.qrCode(), + data: carton.cartonNumber!), + pw.Padding( + padding: const pw.EdgeInsets.all(5), + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + pw.Text(carton.cartonNumber!, + style: pw.TextStyle( + fontSize: 12, + )), + pw.Text(carton.userName!, + style: pw.TextStyle( + fontSize: 10, + )), + pw.Text("${carton.actualWeight} lb", + style: pw.TextStyle( + fontSize: 10, + color: PdfColor.fromInt(0xFF757575))) + ]), + ), + ])); + })); + + List d = await doc.save(); + final path = (await getExternalStorageDirectory())?.path ?? ""; + final file = File("$path/${carton.cartonNumber}.pdf"); + await file.writeAsBytes(d, flush: true); + OpenFile.open(file.path); +} diff --git a/lib/pages/carton/widget/carton_list_row.dart b/lib/pages/carton/widget/carton_list_row.dart index c69dfca..f69ce2f 100644 --- a/lib/pages/carton/widget/carton_list_row.dart +++ b/lib/pages/carton/widget/carton_list_row.dart @@ -1,9 +1,12 @@ import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/carton/model/carton_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; +import '../../../helpers/pdf.dart'; import '../carton_info.dart'; class CartonListRow extends StatelessWidget { @@ -64,7 +67,11 @@ class CartonListRow extends StatelessWidget { ), const SizedBox(width: 15), IconButton( - onPressed: () {}, icon: Icon(AntDesign.qrcode,color: Colors.black)) + onPressed: () { + _pdf(box, context); + }, + icon: + Icon(AntDesign.qrcode, color: Colors.black)) ], ), ), @@ -100,4 +107,11 @@ class CartonListRow extends StatelessWidget { ), ); } + + _pdf(Carton carton, BuildContext context) async { + Carton? c = await context.read().getCarton(carton.id!); + if (c == null) return; + + generateCartonPdf(c); + } } diff --git a/lib/pages/main/model/main_model.dart b/lib/pages/main/model/main_model.dart index 67a963b..0c2a5bd 100644 --- a/lib/pages/main/model/main_model.dart +++ b/lib/pages/main/model/main_model.dart @@ -21,7 +21,7 @@ class MainModel extends ChangeNotifier { set setMessaginToken(token) { this.messagingToken = token; - uploadMsgToken(); + _uploadMsgToken(); } Setting? setting; @@ -84,24 +84,50 @@ class MainModel extends ChangeNotifier { this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true; this.packageInfo = await PackageInfo.fromPlatform(); - if (userListener != null) userListener!.cancel(); + userListener?.cancel(); userListener = Services.instance.authService.getUserStream().listen((_user) { + // if (_user != null) { + // models.forEach((m) => m.initUser(_user)); + // // call diffPrivileges if privilege changed or first time login + // if (this.user == null || _user.diffPrivileges(this.user!)) { + // models.forEach((m) => m.privilegeChanged()); + // } + // if (this.user == null) { + // uploadMsgToken(); + // } + // } else { + // if (this.user != null) { + // models.forEach((m) => m.logout()); + // } + // } + // this.user = _user; + // isLoaded = true; + + bool isFirstTime = user == null && _user != null; + bool diffPrivilege = + _user != null && (user == null || user!.diffPrivileges(_user)); + bool loggingOut = user != null && _user == null; + user = _user; + if (_user != null) { - models.forEach((m) => m.initUser(_user)); - // call diffPrivileges if privilege changed or first time login - if (this.user == null || _user.diffPrivileges(this.user!)) { - models.forEach((m) => m.privilegeChanged()); - } - if (this.user == null) { - uploadMsgToken(); - } - } else { - if (this.user != null) { - models.forEach((m) => m.logout()); + for (final m in models) { + m.initUser(_user); + if (diffPrivilege) { + m.privilegeChanged(); + } } } - this.user = _user; + if (loggingOut) { + for (final m in models) { + m.logout(); + } + } + + if (isFirstTime) { + _uploadMsgToken(); + } + isLoaded = true; notifyListeners(); }); @@ -136,20 +162,23 @@ class MainModel extends ChangeNotifier { return authResult; } - Future? uploadMsgToken() { - if (messagingToken == null || user == null) return null; + Future _uploadMsgToken() { + log.info("messagingToken:$messagingToken::user:$user"); + if (messagingToken == null || user == null) return Future.value(); return Services.instance.userService.uploadMsgToken(messagingToken!); } - Future? removeMsgToken() { - if (messagingToken == null || user == null) return null; + Future _removeMsgToken() { + if (messagingToken == null || user == null) return Future.value(); return Services.instance.userService.removeMsgToken(messagingToken!); } Future signout() async { try { - await removeMsgToken(); - } catch (e) {} + await _removeMsgToken(); + } catch (e) { + log.info(e.toString()); + } await Services.instance.authService.signout(); models.forEach((m) => m.logout()); } diff --git a/pubspec.yaml b/pubspec.yaml index 6f2c415..c53d646 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,6 +54,8 @@ dependencies: cached_network_image: ^3.3.1 flutter_cache_manager: ^3.1.2 flutter_vector_icons: ^2.0.0 + open_file: ^3.3.2 + pdf: ^3.10.8 dev_dependencies: flutter_test: @@ -65,6 +67,7 @@ flutter: assets: - assets/ - assets/local/ + - assets/fonts/ fonts: - family: Roboto