Updated PDF library
This commit is contained in:
parent
28ed4f8092
commit
6830619f75
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -50,8 +51,7 @@ class _DesignEditState extends State<DesignEdit>
|
|||
|
||||
FocusScopeNode _focusNode;
|
||||
TabController _tabController;
|
||||
PDFPageImage _pdfPageImage;
|
||||
String _pdfString;
|
||||
Uint8List _pdfBytes;
|
||||
bool _isLoading = false;
|
||||
|
||||
List<TextEditingController> _controllers;
|
||||
|
|
@ -80,11 +80,11 @@ class _DesignEditState extends State<DesignEdit>
|
|||
|
||||
final design = widget.viewModel.design;
|
||||
_nameController.text = design.name;
|
||||
_headerController.text = design.getSection(kDesignHeader); //design.design;
|
||||
_footerController.text = design.getSection(kDesignFooter); //design.design;
|
||||
_bodyController.text = design.getSection(kDesignBody); //design.design;
|
||||
_headerController.text = design.getSection(kDesignHeader);
|
||||
_footerController.text = design.getSection(kDesignFooter);
|
||||
_bodyController.text = design.getSection(kDesignBody);
|
||||
_productsController.text =
|
||||
design.getSection(kDesignProducts); //design.design;
|
||||
design.getSection(kDesignProducts);
|
||||
_tasksController.text = design.getSection(kDesignTasks);
|
||||
_includesController.text = design.getSection(kDesignIncludes);
|
||||
|
||||
|
|
@ -156,28 +156,12 @@ class _DesignEditState extends State<DesignEdit>
|
|||
return;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
} else if (kIsWeb) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_pdfString = 'data:application/pdf;base64,' +
|
||||
base64Encode(response.bodyBytes);
|
||||
});
|
||||
} else {
|
||||
final document = await PDFDocument.openData(response.bodyBytes);
|
||||
final page = await document.getPage(1);
|
||||
final pageImage =
|
||||
await page.render(width: page.width, height: page.height);
|
||||
page.close();
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_pdfPageImage = pageImage;
|
||||
});
|
||||
}
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
if (response != null) {
|
||||
_pdfBytes = response.bodyBytes;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -234,8 +218,7 @@ class _DesignEditState extends State<DesignEdit>
|
|||
onLoadDesign: _loadDesign,
|
||||
),
|
||||
DesignPreview(
|
||||
pdfPageImage: _pdfPageImage,
|
||||
pdfString: _pdfString,
|
||||
pdfBytes: _pdfBytes,
|
||||
isLoading: _isLoading,
|
||||
),
|
||||
DesignSection(textController: _headerController),
|
||||
|
|
@ -292,8 +275,7 @@ class _DesignEditState extends State<DesignEdit>
|
|||
),
|
||||
Expanded(
|
||||
child: DesignPreview(
|
||||
pdfPageImage: _pdfPageImage,
|
||||
pdfString: _pdfString,
|
||||
pdfBytes: _pdfBytes,
|
||||
isLoading: _isLoading,
|
||||
),
|
||||
),
|
||||
|
|
@ -373,13 +355,12 @@ class DesignSettings extends StatelessWidget {
|
|||
|
||||
class DesignPreview extends StatefulWidget {
|
||||
const DesignPreview({
|
||||
@required this.pdfString,
|
||||
@required this.pdfPageImage,
|
||||
@required this.pdfBytes,
|
||||
@required this.isLoading,
|
||||
});
|
||||
|
||||
final String pdfString;
|
||||
final PDFPageImage pdfPageImage;
|
||||
final Uint8List pdfBytes;
|
||||
|
||||
final bool isLoading;
|
||||
|
||||
@override
|
||||
|
|
@ -387,41 +368,30 @@ class DesignPreview extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _DesignPreviewState extends State<DesignPreview> {
|
||||
double _scrollPosition = 0;
|
||||
final _scrollController = ScrollController(
|
||||
//initialScrollOffset: 0,
|
||||
keepScrollOffset: true,
|
||||
);
|
||||
PdfController _pdfController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_scrollController.addListener(onScrolled);
|
||||
}
|
||||
|
||||
void onScrolled() {
|
||||
_scrollPosition = _scrollController.offset;
|
||||
}
|
||||
String get _pdfString =>
|
||||
'data:application/pdf;base64,' + base64Encode(widget.pdfBytes);
|
||||
|
||||
@override
|
||||
void didUpdateWidget(oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
||||
if (kIsWeb) {
|
||||
WebUtils.registerWebView(widget.pdfString);
|
||||
}
|
||||
|
||||
if (_scrollController.hasClients && _scrollPosition > 0) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((duration) {
|
||||
_scrollController.jumpTo(_scrollPosition);
|
||||
});
|
||||
WebUtils.registerWebView(_pdfString);
|
||||
} else {
|
||||
final document = PdfDocument.openData(widget.pdfBytes);
|
||||
if (_pdfController == null) {
|
||||
_pdfController = PdfController(document: document);
|
||||
} else {
|
||||
_pdfController.loadDocument(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.removeListener(onScrolled);
|
||||
_scrollController.dispose();
|
||||
_pdfController.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
|
@ -434,26 +404,19 @@ class _DesignPreviewState extends State<DesignPreview> {
|
|||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
if (widget.pdfPageImage != null)
|
||||
SingleChildScrollView(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: Card(
|
||||
elevation: 6,
|
||||
child: ExtendedImage.memory(
|
||||
widget.pdfPageImage.bytes,
|
||||
fit: BoxFit.fitHeight,
|
||||
alignment: Alignment.topCenter,
|
||||
),
|
||||
if (kIsWeb)
|
||||
HtmlElementView(viewType: _pdfString)
|
||||
else if (_pdfController != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: PdfView(
|
||||
controller: _pdfController,
|
||||
scrollDirection:
|
||||
isMobile(context) ? Axis.vertical : Axis.horizontal,
|
||||
),
|
||||
)
|
||||
else if (widget.pdfString != null)
|
||||
HtmlElementView(viewType: widget.pdfString)
|
||||
else
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
),
|
||||
SizedBox(),
|
||||
if (widget.isLoading)
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
|
|
|
|||
|
|
@ -13,29 +13,15 @@ import 'package:invoiceninja_flutter/redux/app/app_state.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:invoiceninja_flutter/utils/platforms.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,
|
||||
{String activityId}) 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) {
|
||||
|
|
@ -58,8 +44,8 @@ class PDFScaffold extends StatefulWidget {
|
|||
|
||||
class _PDFScaffoldState extends State<PDFScaffold> {
|
||||
String _pdfString;
|
||||
List<PDFPageImage> _pdfImages;
|
||||
http.Response _response;
|
||||
PdfController _pdfController;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
|
|
@ -69,27 +55,29 @@ class _PDFScaffoldState extends State<PDFScaffold> {
|
|||
setState(() {
|
||||
_response = response;
|
||||
});
|
||||
|
||||
if (kIsWeb) {
|
||||
renderWebPDF(
|
||||
context: context,
|
||||
invoice: widget.invoice,
|
||||
response: response,
|
||||
).then((value) => setState(() {
|
||||
_pdfString = value;
|
||||
WebUtils.registerWebView(_pdfString);
|
||||
}));
|
||||
_pdfString =
|
||||
'data:application/pdf;base64,' + base64Encode(response.bodyBytes);
|
||||
WebUtils.registerWebView(_pdfString);
|
||||
} else {
|
||||
renderMobilePDF(
|
||||
context: context,
|
||||
invoice: widget.invoice,
|
||||
response: response,
|
||||
).then((value) => setState(() {
|
||||
_pdfImages = value;
|
||||
}));
|
||||
final document = PdfDocument.openData(_response.bodyBytes);
|
||||
if (_pdfController == null) {
|
||||
_pdfController = PdfController(document: document);
|
||||
} else {
|
||||
_pdfController.loadDocument(document);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pdfController?.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
|
|
@ -97,85 +85,48 @@ class _PDFScaffoldState extends State<PDFScaffold> {
|
|||
final invoice = widget.invoice;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey,
|
||||
appBar: AppBar(
|
||||
centerTitle: false,
|
||||
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: store.state.headerTextColor),
|
||||
),
|
||||
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',
|
||||
filePath: filePath);
|
||||
}
|
||||
},
|
||||
backgroundColor: Colors.grey,
|
||||
appBar: AppBar(
|
||||
centerTitle: false,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(),
|
||||
),
|
||||
),
|
||||
);
|
||||
title: Text(localization.invoice + ' ' + (invoice.number ?? '')),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text(
|
||||
localization.download,
|
||||
style: TextStyle(color: store.state.headerTextColor),
|
||||
),
|
||||
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', filePath: filePath);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _pdfString == null && _pdfController == null
|
||||
? LoadingIndicator()
|
||||
: kIsWeb
|
||||
? HtmlElementView(viewType: _pdfString)
|
||||
: PdfView(
|
||||
controller: _pdfController,
|
||||
scrollDirection:
|
||||
isMobile(context) ? Axis.vertical : Axis.horizontal,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,37 +156,3 @@ Future<Response> _loadPDF(
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
35
pubspec.lock
35
pubspec.lock
|
|
@ -219,12 +219,12 @@ packages:
|
|||
source: hosted
|
||||
version: "0.4.2+6"
|
||||
extended_image:
|
||||
dependency: "direct overridden"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: extended_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.7.3-dev"
|
||||
version: "1.1.0"
|
||||
extended_image_library:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -238,7 +238,7 @@ packages:
|
|||
name: extension
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.5"
|
||||
version: "0.1.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -488,6 +488,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.4"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.14"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -592,14 +599,14 @@ packages:
|
|||
name: native_pdf_renderer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
version: "2.3.2"
|
||||
native_pdf_view:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: native_pdf_view
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "3.8.0"
|
||||
node_interop:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -677,6 +684,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0-nullsafety"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1010,7 +1024,7 @@ packages:
|
|||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
version: "0.1.2+1"
|
||||
usage:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1095,6 +1109,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1104,4 +1125,4 @@ packages:
|
|||
version: "2.2.1"
|
||||
sdks:
|
||||
dart: ">=2.10.0-0.0.dev <2.10.0"
|
||||
flutter: ">=1.12.13+hotfix.5 <2.0.0"
|
||||
flutter: ">=1.17.0 <2.0.0"
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ dependencies:
|
|||
flutter_json_widget: ^1.0.2
|
||||
webview_flutter: ^0.3.19+8
|
||||
timeago: ^2.0.26
|
||||
native_pdf_view: ^2.2.0
|
||||
native_pdf_view: ^3.8.0
|
||||
#flutter_typeahead: 1.8.0
|
||||
flutter_typeahead:
|
||||
git:
|
||||
|
|
@ -51,10 +51,6 @@ dependencies:
|
|||
version: ^1.0.0
|
||||
#idb_shim: ^1.11.1+1
|
||||
|
||||
dependency_overrides:
|
||||
# Error: No named parameter with the name 'animation'
|
||||
extended_image: 0.7.3-dev
|
||||
|
||||
dev_dependencies:
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
|
|
|
|||
Loading…
Reference in New Issue