Skip to content

chore(repo): migrate to material_ui and cupertino_ui - #2896

Draft
xsahil03x wants to merge 3 commits into
chore/flutter-3.44.0from
chore/migrate-material-cupertino-ui
Draft

chore(repo): migrate to material_ui and cupertino_ui#2896
xsahil03x wants to merge 3 commits into
chore/flutter-3.44.0from
chore/migrate-material-cupertino-ui

Conversation

@xsahil03x

@xsahil03x xsahil03x commented Aug 14, 2026

Copy link
Copy Markdown
Member

Submit a pull request

Linear: FLU-696

CLA

  • I have signed the Stream CLA (required).
  • The code changes follow best practices
  • Code changes are tested (add some information if not applicable)

Description of the pull request

⚠️ Stacked on #2894 — review/merge that first. Base this diff against chore/flutter-3.44.0, not master.

🛑 BLOCKED — not mergeable as-is. 19 type errors remain, and every one of them is upstream. See Why it's blocked.

Flutter has split Material and Cupertino out of the framework into the flutter.dev-published material_ui and cupertino_ui packages — both v1.0.0, published 2026-08-12, the same day as Flutter 3.47 stable.

Both require flutter: >=3.44.0. That is exactly the floor #2894 raises, which is what makes this work possible now and why it is stacked rather than standalone.

What changed

  • 409 import directives across 405 tracked files. package:flutter/material.dartpackage:material_ui/material_ui.dart (403) and package:flutter/cupertino.dartpackage:cupertino_ui/cupertino_ui.dart (6). Only the URI is replaced, so the three imports carrying show/hide clauses keep them. Verified up front that every occurrence is a plain import directive — there are no export directives and no doc/string references to either URI anywhere in the repo.
  • Dependencies added to the 10 pubspecs that need them (material_ui ×10, cupertino_ui ×4), and both registered in melos.yaml's command.bootstrap.dependencies — the workspace's single version registry, where every shared dependency is pinned.
  • directives_ordering reapplied via dart fix (188 files). Renaming the URIs moved them relative to their neighbours; the lint is enabled repo-wide, so this is a consequence of the rewrite, not unrelated churn.
  • Localizations (step 2 of the official guide). GlobalMaterialLocalizations now comes from material_ui and GlobalCupertinoLocalizations from cupertino_ui; GlobalWidgetsLocalizations stays in flutter_localizations, which is still its home. The flutter_localizations import is narrowed with a show so its own GlobalMaterialLocalizations can't collide with material_ui's. The public barrel re-exports each from its new home — this is a public API change for stream_chat_localizations.

Why the migration is hand-rolled, not dart fix

The README says to run dart fix --apply --code=migrate_design_widgets. That does not work in Flutter 3.47. The transform ships in the SDK at fix_data/fix_material/fix_material.yaml, but it is a data-driven replacedBy keyed off the library being deprecated — and package:flutter/material.dart carries no @Deprecated annotation in 3.47. The transform's own comment reads TODO(Piinks): Link eventual deprecation PR. Against the real packages dart fix reports Nothing to fix! even with the lint enabled and the diagnostic firing 13×.

The rewrite reproduces that fix's output byte-for-byte, confirmed against a probe package where the fix does apply.

Why it's blocked

material_ui ships its own implementations, and Flutter 3.47's material.dart does not re-export them. So flutter/material's ThemeData / ThemeExtension / ColorScheme and material_ui's are unrelated types. Reproduced minimally:

error - The argument type 'ThemeData (where ThemeData is defined in .../flutter/lib/src/material/theme_data.dart)'
        can't be assigned to the parameter type 'ThemeData (where ThemeData is defined in .../material_ui-1.0.0/lib/src/theme_data.dart)'

The 19 remaining errors are all that collision, from two dependencies that haven't migrated:

Source Errors Cause
stream_core_flutter 18 StreamTheme extends ThemeExtension<StreamTheme> still binds Flutter's ThemeExtension
dynamic_color 1 DynamicColorBuilder's builder takes Flutter's ColorScheme

stream_core_flutter must migrate first — it's ours, so that's a sequencing decision, not a wait. dynamic_color is third-party and only affects sample_app.

MaterialUiCompatibilityBridge does not rescue this. It is documented as an app-level tool for a modern app hosting legacy widgets; it bridges ThemeData/MaterialLocalizations at runtime and does nothing for compile-time signature mismatches, nor for the reverse case of a legacy app hosting a migrated SDK.

Consumer impact

For the same reason, this is breaking for every consumer of stream_chat_flutter: once our public API speaks material_ui types, an app still on package:flutter/material.dart gets the error above, and Theme.of(context) lookups won't resolve across the two universes at runtime. This needs a major version and coordination with the other Stream SDKs.

Testing

Check Result
dart analyze --fatal-infos @ 3.44.0 floor 19 errors, all upstream (table above); 0 otherwise
dart format, 1004 tracked files 0 changed
stream_chat_flutter_core 362 passed
stream_chat_persistence 302 passed
stream_chat_localizations 3 failed — same upstream blocker, via stream_chat.dart:209
stream_chat_flutter not runnable — blocked at compile

Goldens were not run or regenerated: the package doesn't compile until the blocker clears, and material_ui's widgets may rasterise differently, so the ~40-golden macOS baseline from #2894 needs re-checking once it does.

Follow-up

migrate_design_widgets is deliberately not enabled in analysis_options.yaml. The 3.44 floor analyzer doesn't recognise the rule and exits 2 on unknown names, which would fail legacy_version_analyze. It becomes adoptable when the floor reaches 3.47.

Screenshots / Videos

Not applicable — no intended visual change. Any pixel movement from material_ui's implementations is a finding, not an expectation.

🤖 Generated with Claude Code

Flutter split Material and Cupertino out of the framework into the
flutter.dev-published `material_ui` / `cupertino_ui` packages (both
v1.0.0, 2026-08-12, the same day as Flutter 3.47 stable). Both require
`flutter: >=3.44.0`, which is exactly the floor raised in the parent
commit — that is what unblocks this work, and why it is stacked.

Rewrites all 409 import directives across 405 tracked files:
`package:flutter/material.dart` -> `package:material_ui/material_ui.dart`
(403) and `package:flutter/cupertino.dart` ->
`package:cupertino_ui/cupertino_ui.dart` (6). Only the URI is replaced,
so the three imports carrying `show`/`hide` clauses keep them. Every
occurrence was verified to be a plain import directive first: no export
directives and no doc/string references to either URI exist in the repo.

The migration is done by hand rather than by the README's
`dart fix --apply --code=migrate_design_widgets`. That fix is staged in
the SDK's `fix_data/fix_material/fix_material.yaml` but inert here: it is
a data-driven `replacedBy` keyed off the library being deprecated, and
`package:flutter/material.dart` carries no `@Deprecated` annotation in
3.47 yet (the transform's own TODO reads "Link eventual deprecation
PR"). `dart fix` reports "Nothing to fix!" against the real packages.
The rewrite reproduces that fix's output exactly, confirmed against a
probe package where it does apply.

Reordering the imports moved them relative to their neighbours, so
`directives_ordering` is reapplied via `dart fix` (188 files).

Localizations follow step 2 of the migration guide:
`GlobalMaterialLocalizations` now comes from `material_ui` and
`GlobalCupertinoLocalizations` from `cupertino_ui`, while
`GlobalWidgetsLocalizations` stays in `flutter_localizations`, which is
still its home. The `flutter_localizations` import is narrowed with a
`show` so its own `GlobalMaterialLocalizations` cannot collide with
material_ui's. The public barrel re-exports each from its new home.

BLOCKED, and not mergeable as-is: 19 type errors remain, all of them the
two type universes failing to meet. `material_ui` ships its own
implementations and Flutter 3.47's `material.dart` does not re-export
them, so `flutter/material`'s `ThemeData`/`ThemeExtension`/`ColorScheme`
are unrelated types to `material_ui`'s. 18 come from
`stream_core_flutter`, whose `StreamTheme extends
ThemeExtension<StreamTheme>` still binds Flutter's `ThemeExtension`; 1
from `dynamic_color`, whose `DynamicColorBuilder` takes Flutter's
`ColorScheme`. Both dependencies must migrate before this can land.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 03f82d0d-43fc-4bfb-b6ae-cc712cf0bf38

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

xsahil03x and others added 2 commits August 14, 2026 15:11
`command.bootstrap.dependencies` is the workspace's single version
registry — every shared dependency is pinned there, not only in the
pubspecs that use it. The previous commit added both packages to the 14
pubspec entries but skipped the registry, leaving their versions
unmanaged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Without the lint nothing stops a new file importing
package:flutter/material.dart, silently reintroducing the split between
Flutter's Material types and material_ui's.

Enabling it is safe at the 3.44 floor even though that analyzer does not
recognise the rule. `undefined_lint` is reported against
analysis_options.yaml itself, so it only surfaces when that file is
inside the analysed directory. legacy_version_analyze runs
`cd packages/X/lib && dart analyze --fatal-infos .`, which leaves the
options file out of scope: verified exit 0 from lib/ versus exit 2 from
the package root with the same unknown rule enabled. The main analyze
job runs the latest stable, which knows the rule.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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