add pdf generator

This commit is contained in:
tzw
2024-02-22 17:16:19 +06:30
parent c33d3dda8a
commit cd3a05e064
9 changed files with 139 additions and 27 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -250,6 +250,7 @@ class AuthFb {
StreamSubscription<fb.User?>? authListener; StreamSubscription<fb.User?>? authListener;
Future<void> _start() async { Future<void> _start() async {
await authListener?.cancel();
authListener = _fb.authStateChanges().listen((firebaseUser) { authListener = _fb.authStateChanges().listen((firebaseUser) {
if (firebaseUser == null) { if (firebaseUser == null) {
controller.add(null); controller.add(null);
@@ -261,12 +262,8 @@ class AuthFb {
} }
void _stop() { void _stop() {
if (userListener != null) { userListener?.cancel();
userListener!.cancel(); authListener?.cancel();
}
if (authListener != null) {
authListener!.cancel();
}
} }
controller = StreamController<User?>( controller = StreamController<User?>(

69
lib/helpers/pdf.dart Normal file
View File

@@ -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<void> 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.Widget>[
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<int> 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);
}

View File

@@ -1,9 +1,12 @@
import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/carton/model/carton_model.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import '../../../helpers/pdf.dart';
import '../carton_info.dart'; import '../carton_info.dart';
class CartonListRow extends StatelessWidget { class CartonListRow extends StatelessWidget {
@@ -64,7 +67,11 @@ class CartonListRow extends StatelessWidget {
), ),
const SizedBox(width: 15), const SizedBox(width: 15),
IconButton( 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<CartonModel>().getCarton(carton.id!);
if (c == null) return;
generateCartonPdf(c);
}
} }

View File

@@ -21,7 +21,7 @@ class MainModel extends ChangeNotifier {
set setMessaginToken(token) { set setMessaginToken(token) {
this.messagingToken = token; this.messagingToken = token;
uploadMsgToken(); _uploadMsgToken();
} }
Setting? setting; Setting? setting;
@@ -84,24 +84,50 @@ class MainModel extends ChangeNotifier {
this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true; this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true;
this.packageInfo = await PackageInfo.fromPlatform(); this.packageInfo = await PackageInfo.fromPlatform();
if (userListener != null) userListener!.cancel(); userListener?.cancel();
userListener = userListener =
Services.instance.authService.getUserStream().listen((_user) { 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) { if (_user != null) {
models.forEach((m) => m.initUser(_user)); for (final m in models) {
// call diffPrivileges if privilege changed or first time login m.initUser(_user);
if (this.user == null || _user.diffPrivileges(this.user!)) { if (diffPrivilege) {
models.forEach((m) => m.privilegeChanged()); m.privilegeChanged();
} }
if (this.user == null) {
uploadMsgToken();
}
} else {
if (this.user != null) {
models.forEach((m) => m.logout());
} }
} }
this.user = _user; if (loggingOut) {
for (final m in models) {
m.logout();
}
}
if (isFirstTime) {
_uploadMsgToken();
}
isLoaded = true; isLoaded = true;
notifyListeners(); notifyListeners();
}); });
@@ -136,20 +162,23 @@ class MainModel extends ChangeNotifier {
return authResult; return authResult;
} }
Future<void>? uploadMsgToken() { Future<void> _uploadMsgToken() {
if (messagingToken == null || user == null) return null; log.info("messagingToken:$messagingToken::user:$user");
if (messagingToken == null || user == null) return Future.value();
return Services.instance.userService.uploadMsgToken(messagingToken!); return Services.instance.userService.uploadMsgToken(messagingToken!);
} }
Future<void>? removeMsgToken() { Future<void> _removeMsgToken() {
if (messagingToken == null || user == null) return null; if (messagingToken == null || user == null) return Future.value();
return Services.instance.userService.removeMsgToken(messagingToken!); return Services.instance.userService.removeMsgToken(messagingToken!);
} }
Future<void> signout() async { Future<void> signout() async {
try { try {
await removeMsgToken(); await _removeMsgToken();
} catch (e) {} } catch (e) {
log.info(e.toString());
}
await Services.instance.authService.signout(); await Services.instance.authService.signout();
models.forEach((m) => m.logout()); models.forEach((m) => m.logout());
} }

View File

@@ -54,6 +54,8 @@ dependencies:
cached_network_image: ^3.3.1 cached_network_image: ^3.3.1
flutter_cache_manager: ^3.1.2 flutter_cache_manager: ^3.1.2
flutter_vector_icons: ^2.0.0 flutter_vector_icons: ^2.0.0
open_file: ^3.3.2
pdf: ^3.10.8
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@@ -65,6 +67,7 @@ flutter:
assets: assets:
- assets/ - assets/
- assets/local/ - assets/local/
- assets/fonts/
fonts: fonts:
- family: Roboto - family: Roboto