Skip to content

Add didChangeAlwaysUse24HourFormat to WidgetsBinding and update MediaQuery - #196117

Merged
auto-submit[bot] merged 8 commits into
flutter:masterfrom
prasad2512:fix/issue-194637-framework-always-use-24-hour
Nov 13, 2026
Merged

auto-submit[bot] merged 8 commits into
flutter:masterfrom
prasad2512:fix/issue-194637-framework-always-use-24-hour

Conversation

@prasad2512

Copy link
Copy Markdown
Contributor

Part of #194637
Follow-up to #194670

cc @chunhtai @victorsanni

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

Description

This PR introduces the framework layer integration (Part 2) for runtime 24-hour time format changes, building upon the engine API landed in #194670.

Changes

  1. RendererBinding (packages/flutter/lib/src/rendering/binding.dart):

    • Registered platformDispatcher.onAlwaysUse24HourFormatChanged = handleAlwaysUse24HourFormatChanged;.
    • Added @protected void handleAlwaysUse24HourFormatChanged() {}.
  2. WidgetsBindingObserver (packages/flutter/lib/src/widgets/binding.dart):

    • Added void didChangeAlwaysUse24HourFormat() {}.
  3. WidgetsBinding (packages/flutter/lib/src/widgets/binding.dart):

    • Overrode handleAlwaysUse24HourFormatChanged() to dispatch observer.didChangeAlwaysUse24HourFormat() to all registered observers.
  4. MediaQuery (packages/flutter/lib/src/widgets/media_query.dart):

    • In _MediaQueryFromViewState, implemented didChangeAlwaysUse24HourFormat() to trigger _updateData() when root view's format changes, causing widgets depending on MediaQuery.alwaysUse24HourFormatOf(context) to rebuild with the updated preference.
    • Updated doc comments on MediaQueryData.fromView to list WidgetsBindingObserver.didChangeAlwaysUse24HourFormat and dart:ui.PlatformDispatcher.onAlwaysUse24HourFormatChanged.
  5. TestPlatformDispatcher (packages/flutter_test/lib/src/window.dart):

    • Forwarded onAlwaysUse24HourFormatChanged getter/setter.
    • Updated alwaysUse24HourFormatTestValue and clearAlwaysUse24HourTestValue to invoke onAlwaysUse24HourFormatChanged.
  6. Unit Tests:

    • packages/flutter/test/widgets/binding_test.dart: Added test didChangeAlwaysUse24HourFormat verifying observer dispatch and error handling.
    • packages/flutter/test/widgets/media_query_test.dart: Added test verifying MediaQuery.fromView updates when alwaysUse24HourFormat changes at runtime.
    • packages/flutter_test/test/platform_dispatcher_test.dart: Added test verifying TestPlatformDispatcher.alwaysUse24HourFormatTestValue triggers WidgetsBindingObserver.didChangeAlwaysUse24HourFormat.

…Query

Part of flutter#194637
Follow-up to flutter#194670

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is [test-exempt].
- [x] All existing and new tests are passing.

## Description

This PR introduces the framework layer integration (Part 2) for runtime 24-hour time format changes, building upon the engine API landed in flutter#194670.

### Changes
1. **`RendererBinding` (`packages/flutter/lib/src/rendering/binding.dart`)**:
   - Registered `platformDispatcher.onAlwaysUse24HourFormatChanged = handleAlwaysUse24HourFormatChanged;`.
   - Added `@protected void handleAlwaysUse24HourFormatChanged() {}`.

2. **`WidgetsBindingObserver` (`packages/flutter/lib/src/widgets/binding.dart`)**:
   - Added `void didChangeAlwaysUse24HourFormat() {}`.

3. **`WidgetsBinding` (`packages/flutter/lib/src/widgets/binding.dart`)**:
   - Overrode `handleAlwaysUse24HourFormatChanged()` to dispatch `observer.didChangeAlwaysUse24HourFormat()` to all registered observers.

4. **`MediaQuery` (`packages/flutter/lib/src/widgets/media_query.dart`)**:
   - In `_MediaQueryFromViewState`, implemented `didChangeAlwaysUse24HourFormat()` to trigger `_updateData()` when root view's format changes, causing widgets depending on `MediaQuery.alwaysUse24HourFormatOf(context)` to rebuild with the updated preference.
   - Updated doc comments on `MediaQueryData.fromView` to list `WidgetsBindingObserver.didChangeAlwaysUse24HourFormat` and `dart:ui.PlatformDispatcher.onAlwaysUse24HourFormatChanged`.

5. **`TestPlatformDispatcher` (`packages/flutter_test/lib/src/window.dart`)**:
   - Forwarded `onAlwaysUse24HourFormatChanged` getter/setter.
   - Updated `alwaysUse24HourFormatTestValue` and `clearAlwaysUse24HourTestValue` to invoke `onAlwaysUse24HourFormatChanged`.

6. **Unit Tests**:
   - `packages/flutter/test/widgets/binding_test.dart`: Added test `didChangeAlwaysUse24HourFormat` verifying observer dispatch and error handling.
   - `packages/flutter/test/widgets/media_query_test.dart`: Added test verifying `MediaQuery.fromView` updates when `alwaysUse24HourFormat` changes at runtime.
   - `packages/flutter_test/test/platform_dispatcher_test.dart`: Added test verifying `TestPlatformDispatcher.alwaysUse24HourFormatTestValue` triggers `WidgetsBindingObserver.didChangeAlwaysUse24HourFormat`.

[Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
@github-actions github-actions Bot added a: tests "flutter test", flutter_test, or one of our tests framework flutter/packages/flutter repository. See also f: labels. labels Nov 6, 2026
@prasad2512

prasad2512 commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor Author

Hi @chunhtai and @victorsanni,

Following the landed engine API in #194670, this is Part 2 introducing the framework layer integration (WidgetsBindingObserver.didChangeAlwaysUse24HourFormat, WidgetsBinding dispatch, and MediaQuery runtime refresh) along with comprehensive unit tests.

All local analysis and unit tests are passing cleanly. Ready for review whenever you have a moment. Thank you!

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for reacting to changes in the platform's 24-hour format setting. It adds onAlwaysUse24HourFormatChanged handling to RendererBinding, introduces didChangeAlwaysUse24HourFormat to WidgetsBindingObserver, and updates MediaQuery to rebuild when this setting changes. Additionally, it updates TestPlatformDispatcher to support testing this behavior and includes corresponding unit tests. I have no feedback to provide.

@victorsanni victorsanni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

does this mean we can remove alwaysUse24HourFormat from _viewMetrics in foundation/debug.dart

@prasad2512

prasad2512 commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Yes, exactly! Now that MediaQuery.fromView directly listens to didChangeAlwaysUse24HourFormat via onAlwaysUse24HourFormatChanged, alwaysUse24HourFormat no longer needs to piggyback on _viewMetrics / onMetricsChanged.

I've decoupled alwaysUse24HourFormat from _viewMetrics in foundation/debug.dart, updated operator == and hashCode, adjusted debug_view_metrics_override_test.dart, and removed the redundant onPlatformConfigurationChanged?.call() from TestPlatformDispatcher in commit 91ad86b.

@chunhtai chunhtai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

mostly LGTM. left one comment about test

}

@override
void didChangeAlwaysUse24HourFormat() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

since we also implemented the new API on rentrant observer, we should make sure the test
"Rentrant observer callbacks do not result in exceptions"

calls the handleAlwaysUse24HourFormatChanged

@prasad2512 prasad2512 Nov 9, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done! Added WidgetsBinding.instance.handleAlwaysUse24HourFormatChanged() to the reentrant test in commit b0ae14f9cf, and all binding unit tests are passing cleanly.

@chunhtai

chunhtai commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

is this the final PR? we should update the pr description to fix the issue

victorsanni
victorsanni previously approved these changes Nov 9, 2026

@victorsanni victorsanni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM with a doc suggestion.

@prasad2512

prasad2512 commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks @victorsanni and @chunhtai for the reviews!

In commit b0ae14f9cf:

  • Added the docstring to WidgetsBindingObserver.didChangeAlwaysUse24HourFormat referencing [dart:ui.PlatformDispatcher.onAlwaysUse24HourFormatChanged].
  • Added WidgetsBinding.instance.handleAlwaysUse24HourFormatChanged() to the 'Rentrant observer callbacks do not result in exceptions' test in binding_test.dart (all 34 tests passing cleanly).

Regarding whether this is the final PR and how we should track the remaining work:
To ensure #194637 is fully resolved for physical devices as discussed with @victorsanni on #194670, the physical platform embedders still need to notify the engine of runtime clock format changes (Android FlutterView onResume / Settings.System.TIME_12_24, iOS NSCurrentLocaleDidChangeNotification, and Web).

Because those embedder updates are required to completely resolve the issue on physical devices, we should keep this PR as Part of #194637 so the main tracking issue remains open.

For the upcoming embedder implementations, I personally think doing separate PRs (Part 3 for Android, Part 4 for iOS, Part 5 for Web) would be the best approach. That way:

  1. Each platform's codeowners (Android vs iOS vs Web) can review their respective language/subsystem independently without cross-team delays.
  2. It keeps changes small, atomic, and safe per Flutter tree hygiene, isolating platform-specific presubmit shards.

Let me know if this sounds good to you both, or if you'd prefer a single combined PR instead. Happy to follow whichever approach you and Victor prefer!

@chunhtai

chunhtai commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Thanks for explanation, the current pr description sg then

chunhtai
chunhtai previously approved these changes Nov 9, 2026

@chunhtai chunhtai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@chunhtai chunhtai added the CICD Run CI/CD label Nov 9, 2026

@victorsanni victorsanni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

CI is failing because of unformatted lines in media_query_test.dart and window.dart, can you fix and re-request reviews?

// The 24 hour format announces onAlwaysUse24HourFormatChanged and
// onPlatformConfigurationChanged, and onMetricsChanged is what tells the
// framework to re-read it.
// onPlatformConfigurationChanged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should we also update widgets/debug_view_metrics_override_test.dart? i.e _NotificationRecorder and the test 'tells the framework only about what changed' in the 'propagation' group, which guards end-to-end WidgetsBindingObserver notification isolation.

@prasad2512 prasad2512 Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done! Updated _NotificationRecorder with alwaysUse24HourFormat and added the corresponding assertions to 'tells the framework only about what changed' in commit fd07667. All propagation tests passing cleanly.

expect(widthBuildCount, 2);
expect(heightBuildCount, 2);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

also update existing tests

  • 'MediaQuery.fromView updates on notifications (no parent data)'
  • 'MediaQuery.fromView updates on notifications (with parent data)'

with alwaysUse24HourFormatTestValue assertions.

@prasad2512 prasad2512 Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done! Added alwaysUse24HourFormatTestValue assertions to both tests in commit fd07667, verifying dynamic updates without parent data and isolation when wrapped with parent data.

@prasad2512

prasad2512 commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks @victorsanni and @chunhtai! All review comments have been addressed and fully formatted in commit fd07667 (including _NotificationRecorder updates in debug_view_metrics_override_test.dart and the existing MediaQuery.fromView test assertions). All unit tests pass cleanly. Ready for re-review and CICD label!

@victorsanni victorsanni added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 10, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 10, 2026
@auto-submit

auto-submit Bot commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/196117, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label.

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Nov 10, 2026
@victorsanni victorsanni added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App labels Nov 10, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 11, 2026
@auto-submit

auto-submit Bot commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

auto label is removed for flutter/flutter/196117, Failed to enqueue flutter/flutter/196117 with HTTP 400: Pull request Required status check "Check Code Freeze" is expected..

@prasad2512

Copy link
Copy Markdown
Contributor Author

Hi @victorsanni and @chunhtai,

All CI presubmits and internal Google testing have completed with 100% green! 🎉

When auto-submit attempted to enqueue the PR, it hit:

Failed to enqueue flutter/flutter/196117 with HTTP 400: Pull request Required status check "Check Code Freeze" is expected..

Because this PR originates from a fork, the Material and Cupertino Code Freeze GitHub Actions workflow is awaiting maintainer approval to run (action_required). Since this PR only touches packages/flutter/lib/src/widgets/ and corresponding tests (no changes in material/ or cupertino/), the check will pass cleanly once triggered.

Could one of you please approve/trigger the workflow runs and re-apply autosubmit? Thank you so much!

@victorsanni victorsanni added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 11, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 11, 2026
@auto-submit

auto-submit Bot commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

auto label is removed for flutter/flutter/196117, Failed to enqueue flutter/flutter/196117 with HTTP 400: Pull request Required status check "Check Code Freeze" is expected..

@prasad2512

Copy link
Copy Markdown
Contributor Author

Hi @victorsanni,

Thanks for applying the autosubmit label earlier!

Looking at the GitHub Actions runs, because freeze.yml listens to pull_request types [labeled, unlabeled], each label change spawns a new workflow run that GitHub pauses awaiting outside contributor approval (ACTION_REQUIRED). This causes GitHub branch protection to report Check Code Freeze: Expected — Waiting for status to be reported, which then causes auto-submit to bounce the label and spawn yet another pending run.

Since all presubmits, CI shards, Google testing, and approvals are 100% green and completed, could you please either approve the pending workflow runs or directly Squash and merge the PR? Thank you so much!

@victorsanni victorsanni added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 11, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 11, 2026
@auto-submit

auto-submit Bot commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

auto label is removed for flutter/flutter/196117, Failed to enqueue flutter/flutter/196117 with HTTP 400: Pull request Required status check "Check Code Freeze" is expected..

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Nov 11, 2026
@victorsanni victorsanni added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App labels Nov 11, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 12, 2026
@auto-submit

auto-submit Bot commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

auto label is removed for flutter/flutter/196117, Failed to enqueue flutter/flutter/196117 with HTTP 400: Pull request Required status check "Check Code Freeze" is expected..

@prasad2512

Copy link
Copy Markdown
Contributor Author

Hi @victorsanni and @chunhtai,

All CI presubmits, tree checks, and internal Google testing have now finished with 100% green! 🎉

Currently, the Material and Cupertino Code Freeze workflow run (43089152653) is paused awaiting maintainer approval under "3 workflows awaiting approval". Because of this, GitHub branch protection holds Check Code Freeze as expected, which prevents auto-submit from enqueuing.

Whenever you have a moment today, could you please click Approve and run on the pending workflow runs, or directly Squash and merge? Thank you so much!

@victorsanni victorsanni added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 13, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Nov 13, 2026
Merged via the queue into flutter:master with commit 3e58b20 Nov 13, 2026
31 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: tests "flutter test", flutter_test, or one of our tests CICD Run CI/CD framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants