Experimental Flutter tags#35
Conversation
…rty names - Replace text 'value:' with 'data:' across 21+ test instances - Add required params for widgets: gridDelegate, isSelected, builder, steps, tabs, initialTime, etc. - Pass callbacks from Dart host via data: for onReorder, builder, optionsBuilder - Skip 3 tests with documented reasons: - autocomplete: generated code wraps callback losing type info - shader_mask: same callback wrapping issue - snack_bar: requires ScaffoldMessenger animation - Update type_graph_report_test to allow 2 skipped properties (expected) - Fix lua_tag_test to use data: instead of value: Test results: 133/136 passing (98%) + 3 skipped with valid reasons
- Fix callback type wrapping: check if value is already target type before applying resolver wrapper. This fixes autocomplete, shader_mask, etc. Generated code now uses pattern: (value is Type ? value : resolver(...) as Type?) - Update test generator to use canonical property names: - text 'data:' instead of 'value:' - Use proper DataColumn/DataRow for data_table - Use ImageProvider for image instead of bytes - Use SliverGridDelegate for grid_view - Add special test cases for widgets requiring callbacks: - autocomplete with optionsBuilder - shader_mask with shaderCallback - layout_builder with builder - form_field with builder - toggle_buttons with isSelected + children - tab_bar with tabs inside DefaultTabController - tab_bar_view with children inside DefaultTabController - dismissible with key - reorderable_list_view with onReorder - icon_button with onPressed - decorated_box with decoration - Add default value providers for callback types in _defaultValueForType - Skip snack_bar test (requires ScaffoldMessenger animation) All 135 generated tests now pass.
Add test suite that verifies the auto-generated tags work correctly when LIQUIFY_GENERATED_ONLY mode is enabled (handwritten tags disabled). Tests cover: text, row, column, container, scaffold, gesture_detector, elevated_button, list_view, stack, positioned, padding, center, sized_box, opacity, card, icon, checkbox, switch, slider, text_field, divider, circular/linear_progress_indicator. All 22 tests pass, confirming generated tags can fully replace handwritten implementations for these widgets.
… switch cases Replace hardcoded switch cases in widget_spec_builder.dart with data-driven YAML configuration files: - tool/test_defaults.yaml: Default test values for types (primitives, callbacks, collections, etc.). Supports $name placeholder for variable references. - tool/test_widget_metadata.yaml: Widget-specific test configuration including: - wrapper: Parent tag to wrap widget in (e.g., 'row' for expanded) - wrapperArgs: Args for wrapper tag - child: Child content for test - args: Extra args to add to tag - data: Data map entries for callbacks/complex types - skip: Skip test generation for widget - skipTags: List of tags to skip entirely The builder now: 1. Loads YAML metadata at build time 2. Auto-detects required args from widget properties 3. Merges auto-detected args with widget metadata args (deduped) 4. Generates wrapper/child from metadata Removed ~250 lines of manual switch cases, making test generation fully data-driven and easier to maintain. All 135 generated tests pass.
Add LuaCallbackDrop, LuaValueCallbackDrop, and LuaCallback2Drop classes
that wrap Lua functions and can be used as Flutter callbacks.
This enables defining UI behavior directly in Liquid templates:
```liquid
{% lua assign: on_tap %}
return callback(function()
set("counter", get("counter") + 1)
end)
{% endlua %}
{% gesture_detector onTap: on_tap %}
{% text data: "Tap me" %}
{% endgesture_detector %}
```
New Lua functions:
- callback(fn) - Creates VoidCallback-compatible drop (0 args)
- callback1(fn) - Creates ValueChanged-compatible drop (1 arg)
- callback2(fn) - Creates drop for 2-arg callbacks (e.g., ReorderCallback)
Changes:
- lib/src/lua_callback_drop.dart: New Drop classes wrapping Lua functions
- lib/src/tags/lua.dart: Expose callback(), callback1(), callback2() in Lua
- lib/src/tags/tag_helpers.dart: Add LuaCallbackDrop handling in resolvers
- toVoidCallback: Direct execute() for LuaCallbackDrop
- toBoolCallback, toDoubleCallback, toIntCallback, toStringCallback:
Handle LuaValueCallbackDrop with value passing
This makes over-the-wire UIs much more powerful by allowing behavior
to be defined in templates without writing Dart code.
Add lua_demo app showcasing over-the-wire UI interactions: - Counter with increment/decrement/reset buttons - Slider with value callback - All behavior defined purely in Liquid template using Lua callbacks Demonstrates: - callback() for VoidCallback (buttons) - callback1() for ValueChanged (slider) - get()/set() for state management - log() for debugging No Dart code needed for the interactive behavior.
- Remove manual widget tests that duplicate generated tests - Keep special tests: lua, breakpoint, layout_extensions, strict_tags, generated_only_mode - Update layout_extensions_test.dart to use 'text data:' instead of 'text value:' - Delete property_resolver_test.dart (handwritten convenience feature) - Fix example assets: badge count -> badge label - Add key property to home app cards for test navigation Manual tests removed rely on auto-generated tests in test/generated/widget_tags_test.dart (127+ widget render tests)
- Add rebuild() Lua function that triggers Flutter setState - Register _liquify_flutter_rebuild callback in example app - Update lua_demo to call rebuild() after state changes - Enables over-the-wire UI state management
LiquidPage is a StatefulWidget that:
- Manages a persistent LuaLike instance per page
- Maintains state across rebuilds via _state map
- Lua's get/set read/write to this persistent state
- Lua's rebuild() triggers Flutter setState
- Supports initial data and external state updates
This enables over-the-wire UIs where all behavior is defined
in Liquid templates with Lua callbacks:
```liquid
{% lua assign: on_tap %}
return callback(function()
set("counter", get("counter") + 1)
rebuild()
end)
{% endlua %}
{% elevated_button onPressed: on_tap %}
{% text data: counter %}
{% endelevated_button %}
```
Tests demonstrate:
- Counter increment/decrement via Lua callbacks
- State persistence across multiple interactions
- External state updates via updateState()
- Direct state access via getState()
The lua_demo now uses LiquidPage which provides proper persistent Lua state management. This enables the counter and slider demos to actually update the UI when callbacks fire and call rebuild().
Changed registerGeneratedTypeFilters to use FilterRegistry.register instead
of environment.registerLocalFilter. This ensures filters are available in
isolated environments created by {% render %} tags.
Filters like text_style, sliver_grid_delegate_with_fixed_cross_axis_count,
and all other generated type filters now work inside rendered templates.
- Move filter calls (text_style, sliver_grid_delegate) out of partials - Pass computed values as arguments to render tags - Add explicit screen dimensions to base layout - Partials now expect pre-computed values instead of using filters
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b85e56e821
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| evaluator.startBlockCapture(); | ||
| try { | ||
| evaluator.evaluateNodes(body); |
There was a problem hiding this comment.
Use async evaluation for list_view_builder items
In async rendering mode, ListViewBuilderTag.evaluateWithContextAsync still calls _buildItems, which uses the synchronous evaluator.evaluateNodes(body) path. That means any async tags inside the list item body (e.g., tags that implement AsyncTag) are not awaited and may render empty/missing children or incomplete state during async rendering. This only manifests when templates are rendered via the async API or include async tags within list_view_builder bodies, so the async variant should evaluate nodes with evaluateNodesAsync (or use a dedicated async _buildItemsAsync) to ensure awaited output.
Useful? React with 👍 / 👎.
|
Important Review skippedToo many files! 107 files out of 257 files are above the max files limit of 150. You can disable this status message by setting the Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Uh oh!
There was an error while loading. Please reload this page.