Fix PDF rendering on my smartphone
This commit is contained in:
		| @@ -1,16 +1,14 @@ | ||||
| import 'dart:typed_data'; | ||||
|  | ||||
| import 'package:alert_dialog/alert_dialog.dart'; | ||||
| import 'package:confirm_dialog/confirm_dialog.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:flutter_pdfview/flutter_pdfview.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:logging/logging.dart'; | ||||
| import 'package:moneymgr_mobile/services/storage/expenses.dart'; | ||||
| import 'package:moneymgr_mobile/services/storage/prefs.dart'; | ||||
| import 'package:moneymgr_mobile/utils/extensions.dart'; | ||||
| import 'package:moneymgr_mobile/utils/time_utils.dart'; | ||||
| import 'package:moneymgr_mobile/widgets/pdf_viewer.dart'; | ||||
|  | ||||
| class ExpenseEditor extends HookConsumerWidget { | ||||
|   final Uint8List file; | ||||
| @@ -88,14 +86,7 @@ class ExpenseEditor extends HookConsumerWidget { | ||||
|         children: [ | ||||
|           // Expense preview | ||||
|           Expanded( | ||||
|             child: PDFView( | ||||
|               pdfData: file, | ||||
|               onError: (e) { | ||||
|                 Logger.root.warning("Failed to render PDF $e"); | ||||
|                 alert(context, content: Text("Failed to render PDF $e")); | ||||
|               }, | ||||
|               fitPolicy: FitPolicy.BOTH, | ||||
|             ), | ||||
|             child: PDFViewer(pdfBytes: file, fit: BoxFit.contain), | ||||
|           ), | ||||
|  | ||||
|           SizedBox(height: 10), | ||||
|   | ||||
							
								
								
									
										104
									
								
								moneymgr_mobile/lib/widgets/pdf_viewer.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								moneymgr_mobile/lib/widgets/pdf_viewer.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| import 'dart:io'; | ||||
| import 'dart:math'; | ||||
| import 'dart:typed_data'; | ||||
|  | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:path/path.dart' as p; | ||||
| import 'package:path_provider/path_provider.dart'; | ||||
| import 'package:pdf_image_renderer/pdf_image_renderer.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
|  | ||||
| part 'pdf_viewer.g.dart'; | ||||
|  | ||||
| @riverpod | ||||
| Future<Uint8List> _renderPdf( | ||||
|   Ref ref, { | ||||
|   String? path, | ||||
|   Uint8List? pdfBytes, | ||||
| }) async { | ||||
|   assert(path != null || pdfBytes != null); | ||||
|  | ||||
|   // Create temporary file if required | ||||
|   var isTemp = false; | ||||
|   if (path == null) { | ||||
|     path = p.join( | ||||
|       (await getTemporaryDirectory()).absolute.path, | ||||
|       "render-${Random().nextInt(10000).toString()}+.pdf", | ||||
|     ); | ||||
|  | ||||
|     await File(path).writeAsBytes(pdfBytes!); | ||||
|     isTemp = true; | ||||
|   } | ||||
|  | ||||
|   try { | ||||
|     final pdf = PdfImageRenderer(path: path); | ||||
|     await pdf.open(); | ||||
|     await pdf.openPage(pageIndex: 0); | ||||
|  | ||||
|     // get the render size after the page is loaded | ||||
|     final size = await pdf.getPageSize(pageIndex: 0); | ||||
|  | ||||
|     // get the actual image of the page | ||||
|     final img = await pdf.renderPage( | ||||
|       pageIndex: 0, | ||||
|       x: 0, | ||||
|       y: 0, | ||||
|       width: size.width, | ||||
|       // you can pass a custom size here to crop the image | ||||
|       height: size.height, | ||||
|       // you can pass a custom size here to crop the image | ||||
|       scale: 1, | ||||
|       // increase the scale for better quality (e.g. for zooming) | ||||
|       background: Colors.white, | ||||
|     ); | ||||
|  | ||||
|     // close the page again | ||||
|     await pdf.closePage(pageIndex: 0); | ||||
|  | ||||
|     // close the PDF after rendering the page | ||||
|     pdf.close(); | ||||
|  | ||||
|     return img!; | ||||
|   } finally { | ||||
|     if (isTemp) { | ||||
|       await File(path).delete(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| class PDFViewer extends ConsumerWidget { | ||||
|   final String? pdfPath; | ||||
|   final Uint8List? pdfBytes; | ||||
|   final double? width; | ||||
|   final double? height; | ||||
|   final BoxFit? fit; | ||||
|  | ||||
|   const PDFViewer({ | ||||
|     super.key, | ||||
|     this.pdfPath, | ||||
|     this.pdfBytes, | ||||
|     this.width, | ||||
|     this.height, | ||||
|     this.fit, | ||||
|   }) : assert(pdfPath != null || pdfBytes != null); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final provider = ref.watch( | ||||
|       _renderPdfProvider(path: pdfPath, pdfBytes: pdfBytes), | ||||
|     ); | ||||
|  | ||||
|     // Perform a switch-case on the result to handle loading/error states | ||||
|     return switch (provider) { | ||||
|       AsyncData(:final value) => Image( | ||||
|         image: MemoryImage(value), | ||||
|         width: width, | ||||
|         height: height, | ||||
|         fit: fit, | ||||
|       ), | ||||
|       AsyncError(:final error) => Text('PDF error: $error'), | ||||
|       _ => const CircularProgressIndicator(), | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| @@ -382,14 +382,6 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.4.6" | ||||
|   flutter_pdfview: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: flutter_pdfview | ||||
|       sha256: c402ad1f51ba8ea73b9fb04c003ca0a9286118ba5ac9787ee2aa58956b3fcf8a | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.4.1+1" | ||||
|   flutter_riverpod: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -728,6 +720,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.3.0" | ||||
|   pdf_image_renderer: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: pdf_image_renderer | ||||
|       sha256: "0ec76118b14663f17f9b6a8c29ec59cb1b82e466a3c16fbb2ed9f1b613fc41b7" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.0.1" | ||||
|   petitparser: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
| @@ -89,8 +89,8 @@ dependencies: | ||||
|   path_provider: ^2.1.5 | ||||
|   path: ^1.9.1 | ||||
|  | ||||
|   # PDF viewer | ||||
|   flutter_pdfview: ^1.4.1+1 | ||||
|   # PDF renderer | ||||
|   pdf_image_renderer: ^1.0.1 | ||||
|  | ||||
| dev_dependencies: | ||||
|   flutter_test: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user