I have a flutter app with the following files:

import 'package:flutter/material.dart';

import 'src/app.dart';
import 'src/settings/settings_controller.dart';
import 'src/settings/settings_service.dart';
import 'src/services/database_service.dart';

Future<void> main() async {
  // Set up the SettingsController, which will glue user settings to multiple
  // Flutter Widgets.
  WidgetsFlutterBinding.ensureInitialized();
  await DatabaseHelper.instance.database;
  final settingsController = SettingsController(SettingsService());

  // Load the user's preferred theme while the splash screen is displayed.
  // This prevents a sudden theme change when the app is first displayed.
  await settingsController.loadSettings();

  // Run the app and pass in the SettingsController. The app listens to the
  // SettingsController for changes, then passes it further down to the
  // SettingsView.
  runApp(MyApp(settingsController: settingsController));
}

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter/services.dart';
import 'settings/settings_controller.dart';
import 'settings/settings_view.dart';
import 'pages/main_page.dart';

class MyApp extends StatelessWidget {
  const MyApp({
    super.key,
    required this.settingsController,
  });

  final SettingsController settingsController;

  @override
  Widget build(BuildContext context) {
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    return FutureBuilder<void>(
      future: GoogleFonts.pendingFonts([
        GoogleFonts.nunitoSans(),
      ]),
      builder: (context, snapshot) {
        if (snapshot.connectionState != ConnectionState.done) {
          return const MaterialApp(
            home: Scaffold(
              body: Center(
                child: CircularProgressIndicator(),
              ),
            ),
          );
        }

        final textTheme =
            GoogleFonts.nunitoSansTextTheme(Theme.of(context).textTheme);

        return ListenableBuilder(
          listenable: settingsController,
          builder: (BuildContext context, Widget? child) {
            return MaterialApp(
              restorationScopeId: 'app',
              localizationsDelegates: const [
                AppLocalizations.delegate,
                GlobalMaterialLocalizations.delegate,
                GlobalWidgetsLocalizations.delegate,
                GlobalCupertinoLocalizations.delegate,
              ],
              supportedLocales: const [
                Locale('en', ''),
              ],
              onGenerateTitle: (BuildContext context) =>
                  AppLocalizations.of(context)!.appTitle,
              theme: ThemeData(
                textTheme: textTheme,
                appBarTheme: AppBarTheme(
                  titleTextStyle: textTheme.titleLarge?.copyWith(
                    fontWeight: FontWeight.w600,
                  ),
                ),
                elevatedButtonTheme: ElevatedButtonThemeData(
                  style: ElevatedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 16),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(12),
                    ),
                    textStyle: textTheme.labelLarge,
                  ),
                ),
              ),
              darkTheme: ThemeData.dark().copyWith(
                textTheme:
                    GoogleFonts.nunitoSansTextTheme(ThemeData.dark().textTheme),
                appBarTheme: AppBarTheme(
                  titleTextStyle: textTheme.titleLarge
                      ?.copyWith(fontWeight: FontWeight.w600),
                ),
                elevatedButtonTheme: ElevatedButtonThemeData(
                  style: ElevatedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 16),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(12),
                    ),
                    textStyle: textTheme.labelLarge,
                  ),
                ),
              ),
              themeMode: settingsController.themeMode,
              home: const MainPage(),
              onGenerateRoute: (RouteSettings routeSettings) {
                switch (routeSettings.name) {
                  case SettingsView.routeName:
                    return MaterialPageRoute(
                      settings: routeSettings,
                      builder: (BuildContext context) =>
                          SettingsView(controller: settingsController),
                    );
                }
                return null;
              },
            );
          },
        );
      },
    );
  }
}

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:google_fonts/google_fonts.dart';
import 'recognition_page.dart';
import 'result_page.dart';
import 'live_scan_page.dart';
import '../services/database_service.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  MainPageState createState() => MainPageState();
}

class MainPageState extends State<MainPage> {
  final TextEditingController _ingredientController = TextEditingController();

  @override
  void dispose() {
    _ingredientController.dispose();
    super.dispose();
  }

  Future<void> _navigateToLiveScan() async {
    final result = await Navigator.push<String>(
      context,
      MaterialPageRoute(builder: (context) => const LiveScanPage()),
    );
    if (result != null) {
      setState(() {
        _ingredientController.text = result;
      });
    }
  }

  Future<void> _pickImage() async {
    try {
      final pickedImage =
          await ImagePicker().pickImage(source: ImageSource.gallery);
      if (pickedImage != null) {
        final result = await Navigator.push<String>(
          context,
          MaterialPageRoute(
            builder: (context) => RecognitionPage(xFile: pickedImage),
          ),
        );
        if (result != null) {
          setState(() {
            _ingredientController.text = result;
          });
        }
      }
    } catch (e) {
      _showErrorSnackBar('Error picking image: $e');
    }
  }

  Future<void> _handleIngredients() async {
    final ingredientsText = _ingredientController.text
        .split(',')
        .map((s) => s.trim())
        .where((s) => s.isNotEmpty)
        .toList();

    if (ingredientsText.isEmpty) {
      _showErrorSnackBar('Please enter at least one ingredient.');
      return;
    }

    try {
      final details = await DatabaseHelper.instance
          .fetchIngredientsDetails(ingredientsText);
      if (!mounted) return;

      await Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => ResultPage(ingredientsDetails: details),
        ),
      );
    } catch (e) {
      _showErrorSnackBar('Error fetching ingredient details: $e');
    }
  }

  void _showErrorSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        behavior: SnackBarBehavior.floating,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(
          "Curlify",
          style: theme.textTheme.headlineSmall?.copyWith(
            fontWeight: FontWeight.bold,
          ),
        ),
        elevation: 0,
        backgroundColor: Colors.transparent,
        centerTitle: true,
      ),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.fromLTRB(16, 0, 16, 0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              const SizedBox(height: 16),
              Card(
                elevation: 2,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(16),
                ),
                child: Padding(
                  padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
                  child: TextField(
                    controller: _ingredientController,
                    decoration: const InputDecoration(
                      hintText: 'Type in ingredients separated by a comma...',
                      border: InputBorder.none,
                    ),
                    style: theme.textTheme.bodyMedium,
                    maxLines: 5,
                  ),
                ),
              ),
              const SizedBox(height: 24),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  Expanded(
                    child: ElevatedButton.icon(
                      onPressed: _pickImage,
                      icon: const Icon(Icons.photo_library),
                      label: const Text('Gallery'),
                    ),
                  ),
                  const SizedBox(width: 16),
                  Expanded(
                    child: ElevatedButton.icon(
                      onPressed: _navigateToLiveScan,
                      icon: const Icon(Icons.camera_alt),
                      label: const Text('Scan'),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 24),
              ElevatedButton(
                onPressed: _handleIngredients,
                child: const Text('Analyze Ingredients'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

How do I add a Limit to the the amounts of times a user can analyze something to 10 times, and then he's asked for 1.99 for unlimited scans