import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:logging/logging.dart'; import 'package:moneymgr_mobile/widgets/expense_editor.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:scanbot_sdk/scanbot_sdk.dart'; import 'package:scanbot_sdk/scanbot_sdk_ui_v2.dart' hide IconButton, EdgeInsets; part 'scan_screen.g.dart'; @riverpod Future _scanDocument(Ref ref) async { var configuration = DocumentScanningFlow( appearance: DocumentFlowAppearanceConfiguration( statusBarMode: StatusBarMode.DARK, ), cleanScanningSession: true, outputSettings: DocumentScannerOutputSettings(pagesScanLimit: 1), screens: DocumentScannerScreens( review: ReviewScreenConfiguration(enabled: false), ), ); var documentResult = await ScanbotSdkUiV2.startDocumentScanner(configuration); if (documentResult.status != OperationStatus.OK) { throw Exception("Scanner failed with status ${documentResult.status}"); } // Convert result to PDF var result = await ScanbotSdk.document.createPDFForDocument( PDFFromDocumentParams( documentID: documentResult.data!.uuid, pdfConfiguration: PdfConfiguration(), ), ); final pdfPath = result.pdfFileUri.replaceFirst("file://", ""); return File(pdfPath).readAsBytes(); } class ScanScreen extends HookConsumerWidget { const ScanScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final boredSuggestion = ref.watch(_scanDocumentProvider); restartScan() async { try { final val = ref.refresh(_scanDocumentProvider); Logger.root.info("Load again startup result: $val"); } catch (e, s) { Logger.root.shout("Failed to try again startup loading! $e $s"); } } // Perform a switch-case on the result to handle loading/error states return Padding( padding: const EdgeInsets.all(8.0), child: switch (boredSuggestion) { AsyncData(:final value) when value != null => ExpenseEditor( file: value, onFinished: (e) {}, onRescan: restartScan, ), // No data AsyncData(:final value) when value == null => ScanErrorScreen( message: "No document scanned!", onTryAgain: restartScan, ), // Error AsyncError(:final error) => ScanErrorScreen( message: error.toString(), onTryAgain: restartScan, ), _ => const Center(child: CircularProgressIndicator()), }, ); } } class ScanErrorScreen extends StatelessWidget { final String message; final Function() onTryAgain; const ScanErrorScreen({ super.key, required this.message, required this.onTryAgain, }); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Spacer(flex: 5), Text("An error occurred while scanning"), Spacer(flex: 1), Text(message), Spacer(flex: 1), MaterialButton( onPressed: onTryAgain, child: Text("Try again".toUpperCase()), ), Spacer(flex: 5), ], ), ); } }