Skip to content

Conversation

@gspencergoog
Copy link
Collaborator

@gspencergoog gspencergoog commented Jul 28, 2025

Description

This PR introduces the initial, feature-complete implementation of the fcp_client package, a client-side library for the Flutter Composition Protocol (FCP).

This package allows a Flutter application to render and manage a user interface based on JSON payloads sent from a server, strictly following the protocol defined in the project's documentation. The implementation was developed following the detailed plan in docs/FCP Implementation Plan.md.

Here's the summary of the protocol:

The Flutter Composition Protocol (FCP) is a framework for rendering Flutter user interfaces from a JSON definition. The design is guided by principles of strict separation of concerns, versioning, and targeted updates, with schemas constrained for compatibility with structured data generation models. It draws inspiration from existing solutions like Remote Flutter Widgets (RFW) while introducing a more formalized, contract-driven approach to enhance stability and predictability.

Features Implemented

This PR delivers the full feature set specified in the FCP documentation, covering all 5 implementation milestones:

  • Milestone 1: Core Models & Static Rendering

    • All FCP data models (DynamicUIPacket, WidgetNode, etc.) implemented using Dart extension types for type safety without code generation.
    • A robust layout engine (FcpView) that can parse the non-recursive node list and render a static Flutter widget tree.
    • A CatalogService for loading the client's capabilities catalog and a WidgetCatalogRegistry for mapping widget types to builders.
  • Milestone 2: State Management & Data Binding

    • A central FcpState manager (ChangeNotifier) to hold dynamic UI data.
    • A BindingProcessor service that resolves data paths and applies declarative transformations (format, condition, map).
    • The UI now reactively rebuilds when the state changes.
  • Milestone 3: Event Handling

    • The FcpView exposes an onEvent callback to send user interactions to a backend.
    • Widget builders are wired to construct and emit a standard EventPayload, including contextual arguments.
  • Milestone 4: Targeted Updates

    • State Patcher: Processes StateUpdate payloads using the json_patch standard to efficiently update the FcpState object.
    • Layout Patcher: Processes LayoutUpdate payloads (add, remove, update) to make surgical changes to the UI's structure.
    • An FcpViewController provides a clean, stream-based API for dispatching both state and layout updates to the FcpView.
  • Milestone 5: Advanced Features & Refinement

    • ListViewBuilder: A special builder that uses Flutter's ListView.builder for efficiently rendering dynamic lists, including support for scoped item. bindings.
    • Data Type Validation: Integrates the json_schema package to validate incoming state against schemas defined in the WidgetCatalog.
    • Robust Error Handling: The layout engine now validates widgets and properties against the catalog, rendering a descriptive error widget instead of crashing on violations.

Key Architectural Decisions & Learnings

The development journey, chronicled in docs/JOURNEY.md, led to several key decisions and learnings that shaped the final architecture:

  • Testing Strategy: Integration tests are implemented in a dedicated test fixture application (test_fixtures/m1_integration), which is the correct pattern for testing a Flutter package.
  • Layout Engine: The engine was significantly refactored to be a ChangeNotifier itself. It now passes a Map of named children (e.g., appBar, body) to widget builders instead of a flat list, making builders more robust and less prone to ordering errors.
  • API Documentation: The entire public API surface has been documented with comprehensive doc comments (///) to ensure the package is easy for developers to understand and use.

Testing

The package has extensive test coverage:

  • Unit Tests: Core services like the BindingProcessor, LayoutPatcher, StatePatcher, and DataTypeValidator are thoroughly tested. All data models are also validated.
  • Widget Tests: The FcpView is tested for rendering, event handling, state/layout updates, error handling, and the ListViewBuilder.
  • Integration Tests: A test fixture app in test_fixtures/m1_integration verifies the end-to-end functionality in a running application.

All 74 tests pass, ensuring the package is stable and correct.

@gspencergoog gspencergoog force-pushed the implement_fcp_client branch from c9344bf to 7cb8e20 Compare July 28, 2025 17:12
This commit addresses several TODOs and 'for now' comments in the FCP client implementation.

- Enhances data binding to support nested paths and provide type-safe default values.
- Adds manifest validation to ensure required keys are present.
- Improves error handling by displaying UI errors for invalid state and logging unknown layout operations.
- Implements support for children in list item templates and adds cycle detection.
@gspencergoog gspencergoog changed the title Implement a JSON protocol with a manifest as a package that can render it. A widget that can render a JSON protocol with a catalog and separate state. Jul 28, 2025
@gspencergoog
Copy link
Collaborator Author

/gemini review

This commit introduces a more streamlined and less error-prone API for registering widgets with the fcp_client.

Previously, registering a widget required two separate steps:
1. Calling WidgetCatalogRegistry.register with the widget's name and its builder function.
2. Manually constructing a WidgetCatalog object containing the widget's definition.

This refactoring introduces a new RegisteredWidget class that encapsulates the widget's name, its WidgetDefinition, and its CatalogWidgetBuilder into a single object.

The WidgetCatalogRegistry has been updated to:
- Accept these RegisteredWidget objects directly.
- Include a new buildCatalog() method that automatically generates the WidgetCatalog from the collection of registered items.

All existing tests and the example app have been updated to use this new, more ergonomic API.
This commit addresses several issues to improve the overall health of the codebase.

- Ran dart format and dart fix to ensure consistent formatting and apply automatic fixes.
- Resolved failing widget tests by:
  - Wrapping FcpView in a MaterialApp to provide the necessary Directionality for error widgets.
  - Correcting untyped map literals in test data that were causing _TypeError exceptions.
  - Fixing an incorrect WidgetDefinition for an event in a test.
@gspencergoog gspencergoog merged commit 5fffd1c into flutter:main Jul 29, 2025
1 check passed
@gspencergoog gspencergoog deleted the implement_fcp_client branch August 1, 2025 23:21
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