import 'package:d4rt_formulas/error_handler.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // For Clipboard import 'package:d4rt_formulas/formula_models.dart'; import 'package:get_it/get_it.dart'; import '../corpus.dart'; import '../set_utils.dart'; import 'formula_screen.dart'; import 'package:share_plus/share_plus.dart' as share_plus; import 'formula_editor.dart'; import 'package:share_plus/share_plus.dart'; import 'import_preview_screen.dart'; import '../services/import_service.dart'; class FormulaList extends StatefulWidget { final Corpus corpus; final VoidCallback? onImport; const FormulaList({ super.key, required this.corpus, this.onImport, }); @override State createState() => _FormulaListState(); static String _formulaAndDependenciesToExportStringLiteral(Formula formula) { final corpus = GetIt.instance.get(); final dependencies = corpus.withDependencies(formula); final dependenciesAsMap = dependencies.map((f) => f.toMap()).toList(); for( final f in dependenciesAsMap ){ f.remove("uuid"); } return SetUtils.prettyPrint(dependenciesAsMap); } static void shareFormula(Formula formula) async { try { final exportString = _formulaAndDependenciesToExportStringLiteral(formula); // Share the string await share_plus.SharePlus.instance.share( share_plus.ShareParams( text: exportString, subject: 'Sharing formula: ${formula.name}', ), ); } catch (e, st) { errorHandler.notify(e, st); } } static void copyFormula(BuildContext context, Formula formula) async { try { final exportString = _formulaAndDependenciesToExportStringLiteral(formula); // Copy to clipboard await Clipboard.setData(ClipboardData(text: exportString)); // Show a snackbar to confirm ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Formula and dependencies copied to clipboard!'), duration: Duration(seconds: 2), ), ); } catch (e, st) { errorHandler.notify(e, st); } } } class _FormulaListState extends State { final TextEditingController _searchController = TextEditingController(); String _searchQuery = ''; @override void initState() { super.initState(); _searchController.addListener(_onSearchChanged); } void _onSearchChanged() { setState(() { _searchQuery = _searchController.text.toLowerCase(); }); } @override void dispose() { _searchController.dispose(); super.dispose(); } List get _filteredFormulas { if (_searchQuery.isEmpty) return widget.corpus.getFormulas(); return widget.corpus.getFormulas().where((formula) { final nameMatch = formula.name.toLowerCase().contains(_searchQuery); final tagMatch = formula.tags.any((tag) => tag.toLowerCase().contains(_searchQuery)); return nameMatch || tagMatch; }).toList(); } void _showErrorDialog(String message) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('Error'), content: Text(message), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('OK'), ), ], ); }, ); } @override Widget build(BuildContext context) { return Column( children: [ Padding( padding: const EdgeInsets.all(16.0), child: TextField( controller: _searchController, decoration: const InputDecoration( labelText: 'Search formulas', hintText: 'Search by name or tag...', prefixIcon: Icon(Icons.search), border: OutlineInputBorder(), ), ), ), Expanded( child: ListView.builder( itemCount: _filteredFormulas.length, itemBuilder: (context, index) { final formula = _filteredFormulas[index]; return ListTile( title: Text(formula.name), subtitle: formula.tags.isNotEmpty ? Text('Tags: ${formula.tags.join(', ')}') : null, trailing: Row( mainAxisSize: MainAxisSize.min, children: [ // TOTHINK: Add buttons here, but I don't know which ones ], ), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => FormulaScreen( formula: formula, corpus: widget.corpus, onSave: (formula){ setState(() { // Refresh the list when returning from the formula screen }); }, ), ), ); }, ); }, ), ), ], ); } }