Skip to content

Experimental Flutter tags#35

Draft
kingwill101 wants to merge 19 commits into
masterfrom
feat/flutter_ui
Draft

Experimental Flutter tags#35
kingwill101 wants to merge 19 commits into
masterfrom
feat/flutter_ui

Conversation

@kingwill101
Copy link
Copy Markdown
Owner

@kingwill101 kingwill101 commented Jan 8, 2026

image

…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
@kingwill101 kingwill101 marked this pull request as draft January 8, 2026 11:46
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +198 to +200
evaluator.startBlockCapture();
try {
evaluator.evaluateNodes(body);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 24, 2026

Important

Review skipped

Too 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 reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit 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 help to get the list of available commands and usage tips.

@kingwill101
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 24, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant