import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:pdfrx/pdfrx.dart'; import 'package:printing/printing.dart'; /// Show a PDF preview dialog with Print and Download buttons. /// /// [buildBytes] is called once and cached; the result is shared between the /// preview viewer and the action buttons. Future showPdfPreviewDialog( BuildContext context, { required String title, required String filename, required Future Function() buildBytes, }) { return showDialog( context: context, builder: (_) => _PdfPreviewDialog( title: title, filename: filename, buildBytes: buildBytes, ), ); } class _PdfPreviewDialog extends StatefulWidget { const _PdfPreviewDialog({ required this.title, required this.filename, required this.buildBytes, }); final String title; final String filename; final Future Function() buildBytes; @override State<_PdfPreviewDialog> createState() => _PdfPreviewDialogState(); } class _PdfPreviewDialogState extends State<_PdfPreviewDialog> { late final Future _future; @override void initState() { super.initState(); _future = widget.buildBytes(); } @override Widget build(BuildContext context) { return AlertDialog( contentPadding: EdgeInsets.zero, content: SizedBox( width: 800, height: 900, child: Column( children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Row( children: [ Expanded( child: Text( widget.title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), IconButton( tooltip: 'Print', icon: const Icon(Icons.print), onPressed: () async { final bytes = await _future; await Printing.layoutPdf( onLayout: (_) async => bytes, name: widget.filename, ); }, ), IconButton( tooltip: 'Download', icon: const Icon(Icons.download), onPressed: () async { final bytes = await _future; await Printing.sharePdf( bytes: bytes, filename: widget.filename, ); }, ), IconButton( tooltip: 'Close', icon: const Icon(Icons.close), onPressed: () => Navigator.of(context).pop(), ), ], ), ), const Divider(height: 1), Expanded( child: FutureBuilder( future: _future, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError) { return Center(child: Text(snapshot.error.toString())); } final data = snapshot.data; if (data == null) return const SizedBox.shrink(); return PdfViewer.data(data, sourceName: widget.filename); }, ), ), ], ), ), ); } }