All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			
		
			
				
	
	
		
			116 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'dart:typed_data';
 | 
						|
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
import 'package:go_router/go_router.dart';
 | 
						|
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
						|
import 'package:logging/logging.dart';
 | 
						|
import 'package:moneymgr_mobile/services/router/routes_list.dart';
 | 
						|
import 'package:moneymgr_mobile/services/storage/expenses.dart';
 | 
						|
import 'package:moneymgr_mobile/services/storage/prefs.dart';
 | 
						|
import 'package:moneymgr_mobile/utils/ocr_utils.dart';
 | 
						|
import 'package:moneymgr_mobile/utils/pdf_utils.dart';
 | 
						|
import 'package:moneymgr_mobile/widgets/expense_editor.dart';
 | 
						|
import 'package:riverpod_annotation/riverpod_annotation.dart';
 | 
						|
 | 
						|
part 'scan_screen.g.dart';
 | 
						|
 | 
						|
/// Scan a document & return generated PDF as byte file
 | 
						|
@riverpod
 | 
						|
Future<(Uint8List?, BaseExpenseInfo?)> _scanDocument(Ref ref) async {
 | 
						|
  final prefs = ref.watch(prefsProvider).requireValue;
 | 
						|
 | 
						|
  final pdf = await scanDocAsPDF();
 | 
						|
  final img = await renderPdf(pdfBytes: pdf);
 | 
						|
  final amount = await extractInfoFromBill(
 | 
						|
    imgBuff: img,
 | 
						|
    extractDates: !prefs.disableExtractDates(),
 | 
						|
  );
 | 
						|
  return (pdf, amount);
 | 
						|
}
 | 
						|
 | 
						|
class ScanScreen extends HookConsumerWidget {
 | 
						|
  const ScanScreen({super.key});
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context, WidgetRef ref) {
 | 
						|
    final scanDocProvider = ref.watch(_scanDocumentProvider);
 | 
						|
    final expenses = ref.watch(expensesProvider).requireValue;
 | 
						|
 | 
						|
    restartScan() async {
 | 
						|
      try {
 | 
						|
        ref.invalidate(_scanDocumentProvider);
 | 
						|
        Logger.root.info("Load again startup");
 | 
						|
      } catch (e, s) {
 | 
						|
        Logger.root.shout("Failed to try again startup loading! $e $s");
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return Padding(
 | 
						|
      padding: const EdgeInsets.all(8.0),
 | 
						|
      child: switch (scanDocProvider) {
 | 
						|
        AsyncData(:final value) when value.$1 != null => ExpenseEditor(
 | 
						|
          file: value.$1!,
 | 
						|
          initialData: value.$2,
 | 
						|
          onFinished: (expense) async {
 | 
						|
            await expenses.add(
 | 
						|
              info: expense,
 | 
						|
              fileContent: value.$1!,
 | 
						|
              fileMimeType: "application/pdf",
 | 
						|
            );
 | 
						|
            if (context.mounted) {
 | 
						|
              context.pushReplacement(scansPage);
 | 
						|
            }
 | 
						|
          },
 | 
						|
          onRescan: restartScan,
 | 
						|
        ),
 | 
						|
 | 
						|
        // No data
 | 
						|
        AsyncData(:final value) when value.$1 == 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, textAlign: TextAlign.center),
 | 
						|
          Spacer(flex: 1),
 | 
						|
          MaterialButton(
 | 
						|
            onPressed: onTryAgain,
 | 
						|
            child: Text("Try again".toUpperCase()),
 | 
						|
          ),
 | 
						|
          Spacer(flex: 5),
 | 
						|
        ],
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |