Collapsable description

This commit is contained in:
Your Name 2026-02-09 17:10:47 +01:00
parent 7728498bf9
commit 091dd9d4ec
5 changed files with 61 additions and 32 deletions

View file

@ -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"

View file

@ -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<Object?> parseD4rtLiteral(String arrayStringLiteral). It parses a d4rt array literal (containing maps and arrays) to a List<Object?> 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<UnitSpec> 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

View file

@ -65,6 +65,7 @@ class _FormulaScreenState extends State<FormulaScreen> {
final Map<String, String?> _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<FormulaScreen> {
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),
],
],
),
);
}

View file

@ -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>(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

View file

@ -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<Exception>()));