diff --git a/Makefile b/Makefile index 70f3169..c96ea52 100644 --- a/Makefile +++ b/Makefile @@ -30,3 +30,6 @@ run-linux-debug-native: build-linux-debug-container run-web-debug-native: build-web-debug-container cd build/web && python3 -m http.server $${WEB_PORT:-8081} + +ai: + qwen --prompt-interactive --yolo "Read CLAUDE.md. Implement first task not already done in TODO.md" diff --git a/TODO.md b/TODO.md index f359411..6f22267 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,8 @@ [ ] Means not done [x] Means done -- [ ] Unify error reporting. Create class ErrorHandler that get notified of every catched exception. This class prints the exception in stdout. +- [X] Unify error reporting. Create class ErrorHandler that get notified of every catched exception. This class prints the exception in stdout. +- [ ] Make formula description collapsable in FormulaScreen. Initialy, the description is visible, but the user can hide it. - Refactor formula and unit loading: - [ ] Create method `List parseD4rtLiteral(String arrayStringLiteral). It parses a d4rt array literal (containing maps and arrays) to a List using d4rt - [ ] Remove `fromArrayStringLiteral` from UnitSpec and Formula. @@ -20,3 +21,4 @@ - [ ] From now on, the corpus will be loaded from database instead of assets - [ ] Create method List Corpus.withDependencies(Formula formula). It will return the list of units of the formula, and related units from the corpus. - [ ] Add a Share button to the formula list. It will export the array string literal of the formula with the units from Corpus.withDependencies(). +- [ ] Replace flutter-markdown with flutter-markdown-plus diff --git a/lib/ai/formula_screen.dart b/lib/ai/formula_screen.dart index 24e5e89..7e6d4ec 100644 --- a/lib/ai/formula_screen.dart +++ b/lib/ai/formula_screen.dart @@ -65,6 +65,7 @@ class _FormulaScreenState extends State { final Map _selectedValues = {}; // for string dropdowns String? _result; String? _selectedOutputUnit; + bool _isDescriptionExpanded = true; // Track description expansion state @override void initState() { @@ -194,36 +195,45 @@ class _FormulaScreenState extends State { return const SizedBox.shrink(); } - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( + return Card( + margin: const EdgeInsets.only(bottom: 16), + child: ExpansionTile( + title: Text( 'Description', - style: Theme.of( - context, - ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceVariant, - borderRadius: BorderRadius.circular(8), + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, ), - child: MarkdownBody( - data: widget.formula.description!, - shrinkWrap: true, - builders: { - 'latex': LatexElementBuilder(), - }, - extensionSet: markdown.ExtensionSet( - [LatexBlockSyntax()], - [LatexInlineSyntax()], + ), + initiallyExpanded: _isDescriptionExpanded, + onExpansionChanged: (bool expanded) { + setState(() { + _isDescriptionExpanded = expanded; + }); + }, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceVariant, + borderRadius: BorderRadius.circular(8), + ), + child: MarkdownBody( + data: widget.formula.description!, + shrinkWrap: true, + builders: { + 'latex': LatexElementBuilder(), + }, + extensionSet: markdown.ExtensionSet( + [LatexBlockSyntax()], + [LatexInlineSyntax()], + ), + ), ), ), - ), - const SizedBox(height: 24), - ], + ], + ), ); } diff --git a/lib/error_handler.dart b/lib/error_handler.dart index 2b59b4c..8874bda 100644 --- a/lib/error_handler.dart +++ b/lib/error_handler.dart @@ -14,16 +14,30 @@ class ErrorHandler { // Print the exception to stdout as requested print('ErrorHandler caught exception:'); print(error); - + if (stackTrace != null) { print('Stack trace:'); print(stackTrace); } - + // Call the custom error handler if provided onError?.call(error, stackTrace); } + /// Convenience method to wrap code that might throw exceptions + T handleError(T Function() operation, {T? defaultValue}) { + try { + return operation(); + } catch (error, stackTrace) { + notify(error, stackTrace); + + if (defaultValue != null) { + return defaultValue; + } + + rethrow; + } + } } /// Global instance of ErrorHandler for easy access diff --git a/test/error_handler_test.dart b/test/error_handler_test.dart index 423ef0b..0105ca8 100644 --- a/test/error_handler_test.dart +++ b/test/error_handler_test.dart @@ -31,10 +31,10 @@ void main() { errors.add(error); }; - int result = errorHandler.handleError(() => 42, defaultValue: 0); + int result = ErrorHandler().handleError(() => 42, defaultValue: 0); expect(result, 42); - result = errorHandler.handleError(() { + result = ErrorHandler().handleError(() { throw Exception('Handled exception'); }, defaultValue: 100); @@ -49,7 +49,7 @@ void main() { }; expect(() { - errorHandler.handleError(() { + ErrorHandler().handleError(() { throw Exception('Rethrown exception'); }); }, throwsA(const TypeMatcher()));