David PHAM-VAN

Implement Flutter Web support

... ... @@ -47,3 +47,4 @@ test/diff
ref
!test/golden/*.pdf
.flutter-plugins-dependencies
... ...
... ... @@ -8,6 +8,7 @@
- Use PageTheme in example
- Save shared pdf in cache on Android
- Implement macOS embedding support
- Implement Flutter Web support
## 2.1.9
... ...
import 'dart:async';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/widgets.dart' as fw;
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
... ... @@ -10,13 +11,15 @@ import 'example_widgets.dart';
Future<Document> generateDocument(PdfPageFormat format) async {
final Document pdf = Document(title: 'My Résumé', author: 'David PHAM-VAN');
final PdfImage profileImage = await pdfImageFromImageProvider(
pdf: pdf.document,
image: const fw.NetworkImage(
'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mp&s=200'),
onError: (dynamic exception, StackTrace stackTrace) {
print('Unable to download image');
});
final PdfImage profileImage = kIsWeb
? null
: await pdfImageFromImageProvider(
pdf: pdf.document,
image: const fw.NetworkImage(
'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mp&s=200'),
onError: (dynamic exception, StackTrace stackTrace) {
print('Unable to download image');
});
final PageTheme pageTheme = myPageTheme(format);
... ...
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Printing Example</title>
</head>
<body>
<script src="main.dart.js" type="application/javascript"></script>
</body>
</html>
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
library printing_web;
import 'dart:async';
import 'dart:html' as html;
import 'dart:js' as js;
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
part 'wsrc/print_job.dart';
class PrintingPlugin {
PrintingPlugin(this._channel);
static void registerWith(Registrar registrar) {
final MethodChannel channel = MethodChannel(
'net.nfet.printing',
const StandardMethodCodec(),
registrar.messenger,
);
final PrintingPlugin instance = PrintingPlugin(channel);
channel.setMethodCallHandler(instance.handleMethodCall);
}
final MethodChannel _channel;
Future<dynamic> handleMethodCall(MethodCall call) async {
switch (call.method) {
case 'printPdf':
final String name = call.arguments['name'];
final double width = call.arguments['width'];
final double height = call.arguments['height'];
final double marginLeft = call.arguments['marginLeft'];
final double marginTop = call.arguments['marginTop'];
final double marginRight = call.arguments['marginRight'];
final double marginBottom = call.arguments['marginBottom'];
final _PrintJob printJob = _PrintJob(this, call.arguments['job']);
return printJob.printPdf(name, width, height, marginLeft, marginTop,
marginRight, marginBottom);
case 'sharePdf':
final List<int> data = call.arguments['doc'];
final double x = call.arguments['x'];
final double y = call.arguments['y'];
final double width = call.arguments['w'];
final double height = call.arguments['h'];
final String name = call.arguments['name'];
return _PrintJob.sharePdf(data, x, y, width, height, name);
case 'printingInfo':
return _PrintJob.printingInfo();
}
throw UnimplementedError('Method "${call.method}" not implemented');
}
/// Request the Pdf document from flutter
Future<void> onLayout(
_PrintJob printJob,
double width,
double height,
double marginLeft,
double marginTop,
double marginRight,
double marginBottom) async {
final Map<String, dynamic> args = <String, dynamic>{
'width': width,
'height': height,
'marginLeft': marginLeft,
'marginTop': marginTop,
'marginRight': marginRight,
'marginBottom': marginBottom,
'job': printJob.index,
};
final dynamic result =
await _channel.invokeMethod<dynamic>('onLayout', args);
if (result is List<int>) {
printJob.setDocument(result);
} else {
printJob.cancelJob();
}
}
/// send completion status to flutter
Future<void> onCompleted(_PrintJob printJob, bool completed,
[String error = '']) async {
final Map<String, dynamic> data = <String, dynamic>{
'completed': completed,
'error': error,
'job': printJob.index,
};
await _channel.invokeMethod<dynamic>('onCompleted', data);
}
}
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
part of printing_web;
class _PrintJob {
_PrintJob(this.printing, this.index);
final PrintingPlugin printing;
final int index;
String _jobName;
Future<int> printPdf(
String name,
double width,
double height,
double marginLeft,
double marginTop,
double marginRight,
double marginBottom) async {
_jobName = name;
await printing.onLayout(
this, width, height, marginLeft, marginTop, marginRight, marginBottom);
return 1;
}
static Future<int> sharePdf(List<int> data, double x, double y, double width,
double height, String name) async {
final html.Blob pdfFile = html.Blob(<dynamic>[data], 'application/pdf');
final String pdfUrl = html.Url.createObjectUrl(pdfFile);
final html.HtmlDocument doc = js.context['document'];
final html.AnchorElement link = doc.createElement('a');
link.href = pdfUrl;
link.download = name;
link.click();
return 1;
}
static Map<String, dynamic> printingInfo() {
return <String, dynamic>{
'directPrint': false,
'dynamicLayout': false,
'canPrint': true,
'canConvertHtml': false,
'canShare': true,
};
}
void setDocument(List<int> result) {
final bool isChrome = js.context['chrome'] != null;
if (!isChrome) {
sharePdf(result, 0, 0, 0, 0, _jobName + '.pdf');
printing.onCompleted(this, true);
return;
}
final html.Blob pdfFile = html.Blob(<dynamic>[result], 'application/pdf');
final String pdfUrl = html.Url.createObjectUrl(pdfFile);
final html.HtmlDocument doc = js.context['document'];
final html.IFrameElement frame = doc.createElement('iframe');
frame.setAttribute('style',
'visibility: hidden; height: 0; width: 0; position: absolute;');
frame.setAttribute('src', pdfUrl);
doc.body.append(frame);
frame.addEventListener('load', (html.Event event) {
final js.JsObject win =
js.JsObject.fromBrowserObject(frame)['contentWindow'];
win.callMethod('addEventListener', <dynamic>[
'afterprint',
js.allowInterop<html.EventListener>((html.Event event) {
frame.remove();
printing.onCompleted(this, true);
}),
]);
frame.focus();
win.callMethod('print');
printing.onCompleted(this, true);
});
}
Future<void> cancelJob() async {}
}
... ...
... ... @@ -13,6 +13,8 @@ environment:
dependencies:
flutter:
sdk: flutter
flutter_web_plugins:
sdk: flutter
pdf: "^1.3.15"
dev_dependencies:
... ... @@ -33,3 +35,6 @@ flutter:
pluginClass: PrintingPlugin
macos:
pluginClass: PrintingPlugin
web:
fileName: printing_web.dart
pluginClass: PrintingPlugin
... ...