invoice/lib/utils/pdf.dart

222 lines
7.1 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io' as file;
import 'package:flutter_share/flutter_share.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:invoiceninja_flutter/data/models/invoice_model.dart';
import 'package:flutter/foundation.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/utils/dialogs.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:native_pdf_view/native_pdf_view.dart';
import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:native_pdf_renderer/native_pdf_renderer.dart';
import 'package:invoiceninja_flutter/utils/web_stub.dart'
if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart';
Future<Null> viewPdf(InvoiceEntity invoice, BuildContext context) async {
/*
final localization = AppLocalization.of(context);
if (Platform.isIOS) {
if (await canLaunch(invoice.invitationBorderlessLink)) {
await launch(invoice.invitationBorderlessLink,
forceSafariVC: true, forceWebView: true);
} else {
throw localization.anErrorOccurred;
}
return;
}
*/
showDialog<Scaffold>(
context: context,
builder: (BuildContext context) {
return PDFScaffold(
invoice: invoice,
);
});
}
class PDFScaffold extends StatefulWidget {
const PDFScaffold({this.invoice});
final InvoiceEntity invoice;
@override
_PDFScaffoldState createState() => _PDFScaffoldState();
}
class _PDFScaffoldState extends State<PDFScaffold> {
String _pdfString;
List<PDFPageImage> _pdfImages;
http.Response _response;
@override
void initState() {
super.initState();
_loadPDF(context, widget.invoice).then((response) {
setState(() {
_response = response;
});
if (kIsWeb) {
renderWebPDF(
context: context,
invoice: widget.invoice,
response: response,
).then((value) => setState(() {
_pdfString = value;
registerWebView(_pdfString);
}));
} else {
renderMobilePDF(
context: context,
invoice: widget.invoice,
response: response,
).then((value) => setState(() {
_pdfImages = value;
}));
}
});
}
@override
Widget build(BuildContext context) {
final localization = AppLocalization.of(context);
final invoice = widget.invoice;
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
title: Text(localization.invoice + ' ' + (invoice.number ?? '')),
actions: <Widget>[
FlatButton(
child: Text(
localization.download,
//style: TextStyle(color: Colors.white),
),
onPressed: _response == null
? null
: () async {
if (kIsWeb) {
launch(invoice.invitationDownloadLink,
forceSafariVC: false, forceWebView: false);
} else {
final directory = await getExternalStorageDirectory();
final filePath =
'${directory.path}/${invoice.invoiceId}.pdf';
final pdfData = file.File(filePath);
pdfData.writeAsBytes(_response.bodyBytes);
await FlutterShare.shareFile(
title: 'test.pdf',
//text: 'Example share text',
filePath: filePath);
}
},
),
],
),
body: kIsWeb
? _pdfString == null
? LoadingIndicator()
: _pdfString == ''
? SizedBox()
: HtmlElementView(viewType: _pdfString)
: _pdfImages == null
? LoadingIndicator()
: _pdfImages.isEmpty
? SizedBox()
: Container(
color: Colors.grey,
padding: const EdgeInsets.symmetric(vertical: 16),
child: _pdfImages.length == 1
? Center(
child: Container(
color: Colors.white,
child: Image(
image: MemoryImage(_pdfImages.first.bytes),
height: double.infinity),
),
)
: ListView(
scrollDirection: Axis.horizontal,
children: _pdfImages
.map((page) => Row(
children: <Widget>[
Container(
width: 20,
height: double.infinity,
color: Colors.grey,
),
Container(
color: Colors.white,
child: ExtendedImage.memory(
page.bytes,
fit: BoxFit.fitHeight,
),
),
],
))
.toList(),
),
),
);
}
}
Future<Response> _loadPDF(BuildContext context, InvoiceEntity invoice) async {
final invitation = invoice.invitations.first;
final url = invitation.downloadLink;
final http.Response response = await http.Client().get(url);
if (response.statusCode >= 400) {
showErrorDialog(
context: context,
message: '${response.statusCode}: ${response.reasonPhrase}');
return null;
}
return response;
}
Future<String> renderWebPDF({
@required BuildContext context,
@required http.Response response,
@required InvoiceEntity invoice,
}) async {
if (response == null) {
return '';
}
return 'data:application/pdf;base64,' + base64Encode(response.bodyBytes);
}
Future<List<PDFPageImage>> renderMobilePDF({
@required BuildContext context,
@required http.Response response,
@required InvoiceEntity invoice,
}) async {
final List<PDFPageImage> pages = [];
if (response == null) {
return pages;
}
final document = await PDFDocument.openData(response.bodyBytes);
for (var i = 1; i <= document.pagesCount; i++) {
final page = await document.getPage(i);
final pageImage = await page.render(width: page.width, height: page.height);
pages.add(pageImage);
page.close();
}
return pages;
}