Repository navigation
Inflight/current - #29755
Draft
rmarinho wants to merge 84 commits into
Draft
Inflight/current#29755rmarinho wants to merge 84 commits into
rmarinho wants to merge 84 commits into
Conversation
Member
Author
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 2, 2025 17:32
f5a279d to
c33253a
Compare
Member
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 6, 2025 03:24
98e46e1 to
4cc66a0
Compare
Member
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 6, 2025 15:10
4cc66a0 to
8c2ba96
Compare
Member
Author
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 7, 2025 13:18
24dd756 to
0423cbb
Compare
Member
|
/rebase |
2 similar comments
Member
|
/rebase |
Member
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 10, 2025 16:43
42ca2bd to
b5a6090
Compare
Member
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 11, 2025 16:13
e951517 to
40b6520
Compare
Member
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 16, 2025 17:05
da75aea to
ad851f9
Compare
Member
|
/rebase |
PureWeen
force-pushed
the
inflight/current
branch
from
June 21, 2025 21:40
d56e03b to
263b18d
Compare
Member
|
/rebase |
1 similar comment
Member
|
/rebase |
PureWeen
force-pushed
the
inflight/current
branch
from
June 25, 2025 21:55
3310b65 to
f8f04ff
Compare
Member
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 26, 2025 17:38
4684ea4 to
2938eb4
Compare
PureWeen
force-pushed
the
inflight/current
branch
2 times, most recently
from
June 28, 2025 02:00
205d3a4 to
ad707c9
Compare
Member
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 29, 2025 22:47
b46c65c to
ba454e0
Compare
Member
|
/rebase |
github-actions
Bot
force-pushed
the
inflight/current
branch
from
June 29, 2025 22:50
1b4212f to
c4d674b
Compare
Member
|
/rebase |
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Issue Detail When height is a small non-integer value (e.g., 1.2), the shape renders incorrectly as a thin stroked line instead of a filled rectangle. ### Root Cause - Shape.StrokeThicknessProperty defaults to 1.0. The path and measurement logic in Shape.TransformPathForBounds, Shape.MeasureOverride, Rectangle.GetPath, Ellipse.GetPath, and RoundRectangle.GetInnerPath / InnerPath always applies an inset of StrokeThickness / 2 on each side, even when Stroke is null and no stroke is actually rendered. - For example, a Rectangle with HeightRequest="1.2" and no Stroke would still apply the default stroke inset. This consumed 1.0of the available 1.2 height as a phantom stroke, leaving only a 0.2-pixel-tall fill area. As a result, the rectangle appeared as a thin line instead of a filled rectangle. - BoxView is unaffected because it does not have Stroke or StrokeThickness properties. - Shape geometry is also consumed by `Border`, which must preserve stroke-aware geometry even when the same Shape would not apply an inset when rendered standalone. ### Description of Change - Standalone Shapes now apply the stroke inset only when their own `Stroke` is present. - Added an internal `IShapeWithStroke` contract so Border renderers can explicitly request stroke-aware geometry. - Updated Android, iOS, Mac Catalyst, Windows, and Tizen Border rendering paths to use the appropriate geometry context. - Kept the rendering decision with the consumer instead of storing mutable Border state on shared Shape instances. - Changed the default `Border.StrokeShape` to create a separate `Rectangle` for each Border. - Updated Rectangle, Ellipse, and RoundRectangle path and measurement calculations. ### Validated the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed: Fixes #31330 ### Screenshots | Before | After | |---------|--------| | <img src="https://github.com/user-attachments/assets/ed5ef7d2-7324-4855-af8c-69201ea2152f"> | <img src="https://github.com/user-attachments/assets/8ef27d00-0af8-495b-a616-d441d0f0ed22"> |
…ot square (#39366) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change On Android, a Shell back button whose `BackButtonBehavior.IconOverride` is a `FontImageSource` is drawn stretched. A `‹` glyph comes out flattened and a `●` glyph becomes an oval. **Root cause** Shell sets a `FlyoutIconDrawerDrawable` as the toolbar's navigation icon, and that drawable draws the custom icon inside itself. Its `Draw` set the icon's bounds to its own full bounds, so the icon was stretched to fill them regardless of its shape. A font glyph image is as wide as the measured text and as tall as the font's ascent plus descent (`FontModelResourceDecoder`), so it rarely has the same shape as those bounds. **Fix** `FlyoutIconDrawerDrawable.Draw` now scales the icon to fit inside the bounds with its own aspect ratio and centers it. Each side is at least 1 pixel, so an icon with an extreme aspect ratio, such as a 1000x1 image, is still drawn. An icon with the same aspect ratio as the bounds gets the same bounds as before. No public API changes. The same drawable is used for a custom `Shell.FlyoutIcon`, so a non-square flyout icon keeps its shape as well. I did not test that case separately. **Tests** `ShellTests.BackButtonIconOverrideKeepsItsAspectRatio` (Controls.DeviceTests, Android) pushes a page whose back button icon is a `FontImageSource`, draws the back button to a bitmap, and compares the aspect ratio of what was drawn with the aspect ratio of the icon drawn at its own size. `ShellTests.BackButtonIconOverrideWithExtremeAspectRatioIsDrawn` uses a 1000x1 image as `IconOverride` and checks that the back button still draws something. | | Without fix | With fix | |---|---|---| | `BackButtonIconOverrideKeepsItsAspectRatio` | Fails: expected 0.59, actual 2.14 | Passes | | `BackButtonIconOverrideWithExtremeAspectRatioIsDrawn` | Fails without the 1-pixel minimum | Passes | | Controls.DeviceTests `Category=Shell` | 71 passed, 2 failed (first test only) | 73 passed, 1 failed (both tests) | Run on `main` (f16eb79) on a Lenovo TB323FU tablet, Android 16 (API 36). The remaining failure is `FlyoutHeaderMinimumHeight(CollapseOnScroll)` (`Expected: 56. Actual: 64`), which fails the same way without this change on that tablet. I also checked a square image (`groceries.png`, 512x512) as `IconOverride` in the Sandbox app: the toolbar is pixel-identical with and without the fix. In CI, `IconOverrideInShellBackButtonBehaviorShouldWork`, which uses `coffee.png` (48x56) as `IconOverride`, passed on both Android API 30 legs, so its snapshot is unchanged. **Before** https://github.com/user-attachments/assets/5f32e9e9-2c8c-4364-b844-7c97f34d70c9 **After** https://github.com/user-attachments/assets/7ff47e5d-053e-4573-84e4-efa3a3647342 ### Issues Fixed Fixes #35310 --------- Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com>
### Description of Change Correct `PlatformImage.GetPngDimension` to read the big-endian width and height fields from the PNG IHDR chunk at bytes 16-23 instead of reading the 8-byte PNG signature. The existing stream test now uses a validated 2x3 PNG and asserts the parsed dimensions for both seekable and non-seekable streams. Validation: - `dotnet test src/Graphics/tests/Graphics.Tests/Graphics.Tests.csproj --no-restore` (372 passed) - `dotnet format whitespace --folder . --include src/Graphics/src/Graphics/PlatformImage.cs src/Graphics/tests/Graphics.Tests/PlatformImageTests.cs --verify-no-changes` - `git diff --check` ### Issues Fixed Fixes #39362
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change <!-- Enter description of the fix in this section --> Navigating away from a BlazorWebView during initialization can leave queued native callbacks running after its handler has disconnected. - Ignore late scheme requests when the web view manager is unavailable, including when request interception disconnects the handler. - Cancel late navigation callbacks before accessing the detached virtual view. - Add iOS/Mac Catalyst device regression tests for both callback paths and disconnection during interception. Reproduced the reported null-reference crash in Sandbox before applying the fix. Afterward, Sandbox completed 20 navigation cycles without either lifecycle exception. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #34407 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
…#39429) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details On Windows, CollectionView grid layouts show too much blank space between items. ### Root Cause WinUI applies a default minimum size to each native GridViewItem. This makes item containers larger than their content and creates unwanted empty space. ### Description of Change Set MinHeight to 0 for vertical grids and MinWidth to 0 for horizontal grids. This lets items use their natural size while preserving the configured item spacing. Validated the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #23708 ### Output ScreenShot |Before|After| |--|--| | <img width="800" height="415" alt="image" src="https://github.com/user-attachments/assets/8460ec51-2e71-4da5-af90-71e6aeef3516" /> | <img width="800" height="420" alt="image" src="https://github.com/user-attachments/assets/23458819-ce1a-4584-8739-2e0cad500895" /> |
…op (#39497) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue details On WPF, awaiting `BlazorWebView.DisposeAsync()` can hang when a Razor component or scoped service awaits JavaScript interop during its asynchronous disposal. For example, a scoped service implementing `IAsyncDisposable` can await `IJSRuntime.InvokeVoidAsync` during cleanup. The same problem affects components that perform asynchronous JS cleanup, such as disposing an `IJSObjectReference` module. The disposal-time JS invocation is silently dropped rather than completed or faulted. Consequently, the component or service cannot finish disposal, and the owning `BlazorWebView.DisposeAsync()` remains incomplete. Catching `JSDisconnectedException` does not help because no such exception is raised by this path. The reported real-world scenario involves closing a WPF dialog containing a DevExpress Blazor component whose scoped service releases JS modules during disposal. ### Root cause WPF's `BlazorWebView.DisposeAsync()` calls `_webviewManager.MarkAsDisposing()` before disposing the page through the WebView manager. That flag causes `WebView2WebViewManager.SendMessage()` to return without sending messages. However, page disposal still needs to dispose the Razor renderer and scoped services, and their cleanup code can await JS interop. This ordering blocks the JS invocation that disposal itself is waiting to complete: 1. The control marks the manager as disposing. 2. Page disposal invokes component or scoped-service cleanup. 3. Cleanup awaits a JS interop call. 4. `SendMessage()` drops the outgoing invocation because the manager is already marked as disposing. 5. Cleanup cannot finish, so control disposal cannot finish either. Additionally, the existing `ConfigureAwait(false)` can move native WebView cleanup off the WPF UI thread when manager disposal completes asynchronously. ### Fix description - Keep JS messaging available while awaiting WebView manager disposal, allowing component and scoped-service JS cleanup to complete. - Call `MarkAsDisposing()` after manager/page disposal completes and before disposing the native WebView. - Use `ConfigureAwait(true)` to preserve the WPF UI context for native WebView disposal. - Update the shared manager's documentation to describe the required disposal order. The existing late-message guards in `SendMessage()` remain in place. The control's `_isDisposed` guard is also retained. The functional change is limited to the WPF BlazorWebView implementation. No MAUI handler behavior is changed. ### Why no automated regression test is included No existing automated tests targeting the WPF BlazorWebView implementation were found in this repository. The existing BlazorWebView unit and device test projects target the MAUI implementation; the WPF application is a sample rather than an automated test suite. A representative regression test would require a WPF host running on an STA/UI dispatcher with a real WebView2 instance and JS interop. This PR does not introduce a new WPF test project or test infrastructure. Adding a MAUI test would not cover the affected WPF disposal path. Instead, the fix was verified using a separate executable WPF reproduction harness. That harness and the MAUI Sandbox comparison changes are not included in this PR. ### Verification Verified locally on Windows 11 with a real WebView2 runtime, using both the reported package version (`10.0.110`) and source-built WPF libraries. The WPF reproduction initializes Blazor, instantiates the scoped service, and successfully completes a JS preflight call before disposing the control on the WPF UI thread. A bounded 10-second observation distinguishes completed disposal from the reported hang. | Scenario | Before fix | After fix | | --- | --- | --- | | Scoped service awaits JS during disposal | Service entered disposal, but its JS call and control disposal remained incomplete after 10 seconds | JS call, service disposal, and control disposal completed | | Razor component awaits JS during disposal | Component entered disposal, but its JS call and control disposal remained incomplete after 10 seconds | JS call, component disposal, and control disposal completed | | Scoped service disposes without calling JS | Disposal completed | Disposal completed | All three scenarios completed successfully in three repeated runs each against the patched source-built WPF library. Subsequent runs of the local verification script also passed. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #39471 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…en item spacing changes (#37032) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Issue Details On iOS/MacCatalyst, increasing CollectionView.ItemSpacingat runtime silently shifts ContentOffset, hiding the first item until the user manually scrolls up. ### Root Cause - File: src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs - Any spacing/span change routes: CollectionViewHandler2.OnItemsLayoutPropertyChanged → UpdateLayout() → ItemsViewController2.UpdateLayout(newLayout) → EnsureLayoutInitialized() - EnsureLayoutInitialized() always builds and swaps in a brand-new UICollectionViewCompositionalLayout instance via CollectionView.SetCollectionViewLayout(ItemsViewLayout, false). - Because CollectionView items use self-sizing/estimated dimensions (NSCollectionLayoutDimension.CreateEstimated(30f)), UIKit's self-sizing reconciliation — triggered because the fresh layout instance has no prior size cache — synchronously shifts ContentOffset as a side effect of that single call. - Confirmed via logging: ContentOffset.Y moved 0 → 22.5 → 42.5 → 142.5 as spacing increased 20 → 50 → 100 → 150, with all drift happening inside the SetCollectionViewLayout call (no further drift afterward). ### Description of Change - Captures the offset before the layout swap, restores it if UIKit shifted it. - ResetScrollTracking() prevents a spurious Scrolled delta from being computed against the transient drifted value — this exact pattern (ResetScrollTracking() + ContentOffset assignment) already exists elsewhere in the same file (UpdateItemsSource()), so the fix matches established codebase convention. - Verified: scrolled-away-from-top positions are correctly preserved (not force-reset to zero) — no regression. ### Issues Fixed Fixes #36422 #34785 **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | <Video src="https://github.com/user-attachments/assets/3b6117a5-216c-4cb6-bab5-3fa02e00715b" Width="300" Height="600" /> | <Video src="https://github.com/user-attachments/assets/4bb43152-6f8c-492e-b4ab-e2958081c720" Width="300" Height="600" /> |
Replaced deprecated status bar orientation notifications with UIDevice orientation notifications for iOS. <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change Switches using the deprecated UIApplication.DidChangeStatusBarOrientationNotification and UIApplication.SharedApplication.StatusBarOrientation.IsLandscape() to use UIDevice.OrientationDidChangeNotification and UIDevice.CurrentDevice.Orientation.IsLandscape(); instead ### Issues Fixed Fixes #39182 #39182
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Root Cause : - When an iOS splash screen uses an unresized raster image, the generated storyboard could reference the image with its `Resources/` directory prefix. - The image is bundled by filename, so the storyboard’s reference did not match the bundled image name and the splash image could appear blank. ### Description of Change - **Storyboard image reference update:** - The image reference in the storyboard is now set to just the file name instead of the full path, ensuring the storyboard references the bundled image correctly. (`GenerateSplashStoryboard.cs`) - **Unit test addition:** - A new unit test, `UnresizedRasterSplashReferencesBundledImageName`, has been added to verify that unresized raster splash images are correctly referenced by their bundled file name in the storyboard. (`GenerateSplashStoryboardTests.cs`) <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #28751 ### Tested the behavior in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [ ] Mac | Before Issue Fix | After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/80653f8b-4d02-45d8-b98c-98a2da2b1976"> | <video src="https://github.com/user-attachments/assets/c322df15-fdcc-46ed-8a8a-63336ac15c9f"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
…ources (#39470) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! Recheck source compatibility on every `TypedBinding.ApplyCore` invocation instead of caching it alongside the target property's default value. During Windows CollectionView recycling, a template can temporarily lose its ancestor. `RelativeBindingSource` intentionally applies a null source until the ancestor becomes available again. The previously cached successful type check allowed the null source through to SourceGen getters such as `source => (source.UseCommand, true)`, causing a first-chance `NullReferenceException`. The reverse transition could also leave a binding using a cached unsuccessful check after a compatible source became available. This change prevents getter invocation for null or incompatible sources, restores binding values when a compatible source returns, and deduplicates consecutive source-type mismatch diagnostics. It does not retain the source strongly or change the public API. The fix is in shared binding code; Windows is the runtime-validated platform, not an exclusive scope claim. Regression tests count getter invocations, so they detect the exception even when the binding engine catches it. Coverage includes valid/null/incompatible/valid transitions, fallback values, initial incompatible-source recovery, and OneWay, OneTime, and TwoWay modes. - Reproduced with the public sample from #38667 using Microsoft.Maui.Controls 10.0.110, SourceGen, and Windows ARM64. - Added an instrumented runtime harness in a local scratch copy of the sample: incremental animated scrolling, large scrolling jumps, dynamic-resource replacement, ItemsSource reset, and ancestor detach/reattach. - Before: 6,094 matching first-chance exceptions in generated command getters. These were caught by the binding engine; the standalone process did not terminate. - After: zero matching exceptions in two complete five-scenario runs. Confirmed the running app loaded the source-built Windows Controls assembly, and a real item-command click still updated the UI. - Regression cases failed against the unchanged implementation and pass with the fix. The final five regression cases pass locally. - Broader TypedBinding tests: 115 passed, 2 skipped, and one `FailToConvert` failure also reproduced on the unchanged baseline. - Runtime harness/logs are local investigation artifacts, not additions to the repository. Android and iOS runtime verification has not been performed. Fixes #38667 ---------
…bBar overflow menu (#39412) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change On Windows, clicking a Shell tab with more than one ShellContent in the overflow menu of the top tab bar (the ... button) crashed the app with E_BOUNDS (invalid vector subscript). The crash is inside WinUI NavigationView. From what I see in the WinUI code, in Top mode it cant find the container of a data bound item that sits in the overflow menu, so the clicked item never gets IsSelected, only IsChildSelected, and when it expands right after the click WinUI reads past the end of the selected index path. MAUI always fills the tab bar through MenuItemsSource, so every tab with sub tabs runs into it. A plain WinUI NavigationView with MenuItemsSource and a similar item template crashes the same way. Fixing up the selection state after the click only helps for the first click, other overflow bugs in WinUI show up after that (for example picking a sub tab from the overflow menu and closing the menu later crashes again). So now ShellItemHandler sets SelectsOnInvoked to false on overflow menu containers that have sub tabs, and clears it when the container leaves the overflow menu. MapMenuItems also updates the items that are already in the overflow menu, because a tab can get or lose sub tabs while it sits there. A click on such a tab just expands it, picking one of its sub tabs navigates like before and WinUI moves the tab into the bar. Tabs in the bar work like before. There are four device tests. The first one opens a tab with one ShellContent from the overflow menu, then clicks the tab with sub tabs, picks Sub B and checks the navigation. The second one adds and removes a sub tab of a tab that already sits in the open overflow menu and checks the item follows. The third one moves a tab with sub tabs from the overflow menu back into the bar and checks it gets selected there like before. The fourth one applies the NavigationView template again and checks the new overflow menu behaves the same. Without the fix the click makes WinUI kill the whole test app, so the tests check SelectsOnInvoked before clicking to fail in a normal way. ### Issues Fixed Fixes #37985 --------- Co-authored-by: Empiree <Empiree@users.noreply.github.com> Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…anges (#38441) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Issue Details - On Mac Catalyst and iOS, when a CollectionView is initially populated with a larger number of items, it expands and reports a larger rendered height through the SizeChanged event. If the ItemsSource is subsequently updated with fewer items, the CollectionView retains the previously measured height instead of recalculating and shrinking to match the new content size. ### Root Cause - InvalidateMeasureIfContentSizeChanged() ran in ViewWillLayoutSubviews(), where CV2's compositional layout could still expose the previous content size because estimated, self-sizing cells had not completed layout. Once UIKit produced the updated size later in the layout pass, MAUI received no subsequent measure invalidation and retained the stale CollectionView height. ### Description of Change - Moved the CV2 content-size check to ViewDidLayoutSubviews() so MAUI invalidates and remeasures the CollectionView after UIKit has updated the compositional layout's content size. Added the ViewDidLayoutSubviews override to ItemsViewController2 and updated the public API files for iOS and Mac Catalyst. ### Issues Fixed Fixes #38276 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Before | After | |----------|----------| | <video src="https://github.com/user-attachments/assets/bd45e97e-0915-4296-9fb0-cf5845cabfaf"> | <video src="https://github.com/user-attachments/assets/503bd075-9031-4029-b2aa-b84c39be8fb9"> | --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…sposed renderer (#39458) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details On iOS 26, a native back navigation followed by dismissal of a modal NavigationPage can leave a queued cleanup continuation running after its NavigationRenderer has been disposed and its native UINavigationController released. The continuation throws ObjectDisposedException when it reads ViewControllers. Because its task is not observed, the exception subsequently surfaces through TaskScheduler.UnobservedTaskException. Applications monitoring unobserved task exceptions can record this as an application error even though navigation has already completed. ### Root Cause NavigationRenderer.RemoveViewControllers attaches a continuation to the page's appeared/disappeared task. When that task completes with false, the iOS 26 cleanup branch checks ViewControllers.Contains(controller) before disposing the popped controller. The continuation previously checked only the navigation task's result. It did not check whether the renderer had been disposed while the continuation was queued. Reading ViewControllers after release of the native renderer throws ObjectDisposedException. Simply returning when the renderer is disposed is insufficient: its disposal loop only cleans up controllers still in ViewControllers. A controller already removed by native pop still needs disposal to detach its page and toolbar subscriptions. Additionally, clearing that controller's Child during cleanup calls UpdateIconColor, which must not update a disposed navigation renderer. ### Description of Change <!-- Enter description of the fix in this section --> - Avoid reading ViewControllers when the navigation renderer is disposed, while still disposing the captured popped controller so its cleanup is not skipped. - Preserve the existing iOS 26 navigation-stack membership check for active renderers, including its interrupted-transition behavior. - Guard ParentingViewController.UpdateIconColor against updating a disposed navigation renderer, allowing controller disconnection to finish safely. - Add parameterized device regression coverage for both native PopViewController and PopToRootViewController after modal dismissal. - The tests delay the real continuation, wait for the native renderer handle to be released, and then execute and await the continuation. They retain the popped page and controller, change IconColor, title and toolbar properties after dismissal, and verify the old controller is disposed. There are no public API changes or new dependencies. The baseline Sandbox exception matches the reported framework call chain: NSObject.get_SuperHandle -> UINavigationController.get_ViewControllers -> NavigationRenderer.RemoveViewControllers, and surfaces through TaskScheduler.UnobservedTaskException. This is a controlled reproduction of the reported race. The ordinary scenario did not reproduce the production timing naturally. The diagnostic does not synthesize exceptions or explicitly dispose the renderer. ### Validation - The original controlled Sandbox diagnostic produced five matching exceptions before the fix and none afterward. - The extended retained-page tests failed with the initial early-return fix for both native pop and pop-to-root: changing IconColor reached UpdateIconColor -> UpdateBarTextColor after renderer disposal. Both pass with the cleanup-safe implementation. - Merged current main without rebasing, preserving its new back-button tests alongside the disposal regression tests. The post-merge iOS 26.5 simulator run passed **26 tests, 0 failures**; the build completed with **0 warnings and 0 errors**. Exact post-merge validation commands (from the repository root): ```bash export PATH="$PWD/.dotnet:$PATH" export DOTNET_ROOT="$PWD/.dotnet" dotnet format Microsoft.Maui.sln --no-restore --exclude Templates/src --exclude-diagnostics CA1822 --include src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs --verbosity quiet # Passed. dotnet tool restore # Passed; restored the updated XHarness tool required after merging main. pwsh .github/skills/run-device-tests/scripts/Run-DeviceTests.ps1 -Project Controls -Platform ios -Configuration Debug -DeviceUdid CD32F3F6-DF24-4CA5-8D8C-4FC360DB5BAD -SkipXcodeVersionCheck -TestFilter Category=NavigationPage -Timeout 00:05:00 # Passed: 26 tests, 0 failures. Used a separate local -OutputDirectory for captured evidence. ``` Validation used an iPhone 17 Pro simulator running iOS 26.5. SkipXcodeVersionCheck was needed because installed Xcode differs from the repository iOS SDK's expected version. Physical devices, Mac Catalyst, pre-iOS 26, and interrupted interactive swipe-back were not separately validated. Hosted CI results for the updated head are pending. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #39391 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
…plete Requests (#39469) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Root cause The issue occurs because HybridWebViewHandler.MapEvaluateJavaScriptAsync is an async void command mapper that awaits an internal JavaScript evaluation task. On iOS, WKWebView can report a native evaluation error, such as WKErrorDomain code 5, which faults the task. Previously, the mapper did not catch the exception, allowing it to escape through the synchronization context as an unhandled exception that could terminate the application. The original request returned to the caller was never completed, preventing callers from catching the failure when awaiting EvaluateJavaScriptAsync. InvokeJavaScriptAsync was also affected because it uses the same evaluation command internally. Additionally, when the platform view was unavailable, the mapper returned without completing the request because the subsequent cancellation check was unreachable, potentially leaving the caller waiting indefinitely. ### Solution description The fix involves updating the shared evaluation mapper to: - Catch evaluation exceptions and forward them to the caller through TrySetException. - Complete the request as canceled when the platform view is unavailable or evaluation is canceled. - Preserve existing script preparation and result normalization, including returning null for null results rather than an empty string. - Although the reported failure occurs on iOS, the fix belongs in the shared mapper because that is where the exception escaped and the caller's request remained incomplete. No task-manager interface changes are required. Validated the behavior in the following platforms - [x] iOS - [ ] Mac - [ ] Android - [ ] Windows ### Issues Fixed Fixes #39078 ### Output ScreenShot |Platform|Before|After| |--|--|--| |iOS|<video src="https://github.com/user-attachments/assets/afa4e0fd-2e45-4753-92a1-9572ae188271">|<video src="https://github.com/user-attachments/assets/6d945e62-b5a6-4ca4-8327-61aab1013f84">|
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Issue Details On Android, when Shell uses FlyoutBehavior.Locked with a right-to-left (RTL) flow direction, the content does not fit into the remaining space beside the flyout. The flyout appears on the right, but the content is positioned beneath it instead of occupying the available space on the left. This issue occurs only with the Shell renderer and does not occur with the .NET 11 Shell handler. ### Root Cause The renderer positions the flyout using GravityFlags.Start, which resolves to the left in LTR and the right in RTL. However, in locked mode, SetPadding reserves space for the flyout on the physical left edge, regardless of the layout direction. As a result, in RTL mode, the flyout and the reserved content space are positioned on opposite sides. ### Description of change Updated ShellFlyoutRenderer.cs: - Replaced SetPadding with SetPaddingRelative in locked mode so the reserved space follows the layout direction and aligns with the flyout's position. - Replaced PaddingRight with PaddingEnd to preserve padding on the correct opposite edge. - Updated the padding resets for Flyout and Disabled modes to clear the start-relative padding and prevent leftover spacing when switching away from locked RTL mode. **Reference:** https://github.com/dotnet/maui/blob/net11.0/src/Controls/src/Core/Handlers/Shell/ShellHandler.Android.cs#L325 ### Why tests were not added This scenario is already covered by Issue32419.VerifyShellMenuItemsAlignedInRTL, so no additional test is needed. ### Issues Fixed Fixes #39461 ### Screenshots | Before Issue Fix | After Issue Fix | |----------|----------| | <img width="540" height="868" src="https://github.com/user-attachments/assets/9c5ed988-c5cb-4ac0-a0fe-ea6e9f7b6471"> | <img width="540" height="868" src="https://github.com/user-attachments/assets/e2984d03-af5b-42c3-abad-e2466297d450"> |
…39484) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details - On iOS and Mac Catalyst, a Button with a gradient background and a non-zero CornerRadius displays a rounded border, but the gradient background extends beyond the rounded corners. - Solid-color backgrounds are not affected. ### Root Cause - PR #33346 introduced a new button-specific background update path to correctly clear backgrounds during VisualState changes. - During this change, the button's stroke information (including CornerRadius) was no longer passed through the background rendering flow. - As a result, gradient background layers no longer received the CornerRadius value, causing the gradient to render with square corners while the native button itself remained rounded. ### Description of Change **Button background rendering improvements:** * Updated the `UpdateBackground` extension method in `ButtonExtensions.cs` to accept an optional `IButtonStroke` parameter, allowing the background rendering logic to respect the button's `CornerRadius`. The method now passes this parameter to the underlying view background update logic. * Modified the `MapBackground` method in `ButtonHandler.iOS.cs` to pass the button instance as the stroke parameter when updating the background, ensuring the platform view can access the `CornerRadius` property. **Test coverage:** * Added a new test page (`Issue39450.cs`) to verify that various button backgrounds—linear gradient, radial gradient, and visual state-driven backgrounds—are clipped to the rounded corners as expected. * Introduced a corresponding UI test (`Issue39450.cs` in `TestCases.Shared.Tests`) that toggles button visual states and checks via screenshots and label assertions that the background remains within the rounded borders. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #39450 ### Tested the behavior in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Before | After | |----------|----------| | <img src="https://github.com/user-attachments/assets/95766dff-c233-487a-879f-73825e94c1a0"> | <img src="https://github.com/user-attachments/assets/56960788-249b-4e58-8efa-6db61bc00df7"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details On Windows, a regular WebView renders blank when used alongside a HybridWebView. This regression was originally reported in #34558 and reported again in #39297 after the previous fix, #35092, was reverted by #35814 because of HybridWebView device-test failures in CI. The reported two-window scenario was reproduced in Sandbox using local HTML to avoid network dependencies. In both initialization orders, the first control loaded successfully while the second failed WebView2 initialization with COMException `0x8007139F`. ### Root Cause WinUI initializes its default WebView2 environment with `Language` set to the first entry in `Windows.Globalization.ApplicationLanguages.Languages`. HybridWebView creates an explicit environment without applying the same language default. WebView2 controls sharing a user data folder require compatible browser-process environment options. The different language defaults make these environments incompatible, preventing the second control from initializing. ### Fix Details Apply WinUI's application-language default when the HybridWebView environment language is unspecified. - Preserve explicitly configured environment languages. - Preserve custom user data folders, profiles, and other environment/controller settings. - Retain a single explicit environment/controller initialization path. - Leave regular WebView initialization and non-Windows implementations unchanged. Unlike the reverted fix, this does not switch between default and explicit initialization depending on whether settings are customized. It resolves the underlying language mismatch for both default and customized initialization. #### Validation Added focused Windows device tests covering: - Default coexistence in both initialization orders. - Coexistence with a custom HybridWebView profile. - Coexistence with explicitly supplied environment options whose language is unspecified. - Preservation of an explicitly configured language. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #34558 Fixes #39297 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
… to Null (#39513) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Issue Details: CollectionView with an ItemsSource initially set to a list, the EmptyViewTemplate is not displayed when the ItemsSource is subsequently set to Null. ### Root Cause: The Windows handler clears the previous data source, then returns immediately if the new ItemsSource is null. This bypasses UpdateEmptyViewVisibility(), leaving the empty-view visibility stale. ### Description of Changes: Updated ItemsViewHandler.Windows.cs to refresh empty-view visibility before returning for a null source. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #28334 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [ ] Android - [x] Windows - [ ] iOS - [ ] Mac | Before | After | |---------|--------| | **Windows**<br> <video src="https://github.com/user-attachments/assets/fcde9fcf-588b-432f-b24f-5266a2925c3a" width="600" height="300"> | **Windows**<br> <video src="https://github.com/user-attachments/assets/f87e3159-5fb1-4585-85b5-03b1c650f914" width="600" height="300"> |
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Review the 30 unique observed unsuppressed PoliCheck fingerprints, accounting for all 48 raw occurrences and coalesced matches. These are contextual scanner matches, not 30 independently confirmed product defects. - Change the editable Maps sample label to **Country/region name** and clarify four related `Locale`/`Placemark` documentation descriptions. - Replace the adapted, unattributed accessibility quotation with unquoted owned guidance: retain font scaling for people with low vision and prioritize accessibility over visual polish. Do not treat quotation marks or helpful intent as a term-guidance exemption. - Clarify two comments and expand two local gate-result variable names throughout `Write-MarkdownReport`, preserving reporting and retry logic. Together, these source changes address seven observed fingerprints. - Add 23 exact observed primary fingerprints, each with its own contextual justification, to the existing active `eng/automation/guardian/source.gdnsuppress` file. Retain contributor attribution, font identifiers, public/native API references, and technical usages. Remove the proposed rule 211960 suppression rather than suppressing editable accessibility prose. - Preserve all 15 preexisting suppression entries, their metadata, public API baselines, XAML bindings, and scan-policy/pipeline configuration. No alternate signatures or broad exclusions are added. No other open PR addressing this issue was found when preparing this approach. ### Validation - **10 existing focused Pester tests passed** (`Write-MarkdownReport*` in `Verify-TestsFail.Tests.ps1`; 101 unrelated tests not selected). This evidence remains applicable to the Markdown/JSON-only follow-up: verifier and test-file bytes are unchanged, so Pester was not rerun. - Follow-up checks confirm that only the proposed accessibility suppression was removed; the other 23 new records, all 15 prior records, and metadata remain unchanged. The owned accessibility paraphrase and updated JSON/counts pass the new scope and whitespace checks. - Original and edited PowerShell parse successfully. Significant tokens are identical after normalizing the two local renames; all 14 renamed references remain in the same function, without name collisions. - Checked JSON with duplicate-key rejection, exact added-fingerprint membership, individual justifications, preservation of prior entries and metadata, unchanged APIs/bindings/executable C# and pipeline text, XAML/XML parseability, and `git diff --check`. No fresh PoliCheck/Guardian scan or full MAUI/native build was run, and no CI run was manually queued. This bounded main-branch cleanup does not assert zero raw matches or release/global compliance. ### Issue Addressed Addresses #39528. ---------
…t Snapshots for Issue (#39526) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Root cause The issue occur because of the Android ImageButton rendering its border as part of the view’s background, behind its image. Image scaling can draw the image into the area reserved for the border. With AspectFill, the image may extend beyond the content area, while with Center, a large image can also overlap the border. The image then obscures the background stroke, making some or all sides appear missing. This affects URI and file image sources. ### Solution description The fix involves enabling CropToPadding on the Android ShapeableImageView created by ImageButtonHandler. This setting ensures that image drawing is clipped to the view’s padded content area instead of extending into the area reserved for the border. As a result, the image no longer obscures the background stroke, and the border remains visible on all sides. The setting is applied in the shared handler setup, addressing the issue for both AspectFill and Center image rendering without changing the existing image scaling modes. **Snapshot Updates:** I have replaced the existing snapshots with updated versions to reflect the expected visual changes introduced by enabling CropToPadding. This clips image drawing to the padded content area, preventing the image from overlapping the border and ensuring the border remains visible. - VerifyImageButtonAspect_AspectFillWithImageSourceFromFontImage - VerifyMaterial3ImageButtonAspect_AspectFillWithImageSourceFromFontImage **Additional Test Snapshots and Restriction Removal** I have added the required snapshots and removed the test restrictions for the following test cases related to issue #29956. **ImageButton test cases:** - VerifyImageButtonAspect_AspectFillWithImageSourceFromUri - VerifyImageButtonAspect_AspectFillWithImageSourceFromFile - VerifyImageButtonAspect_CenterWithImageSourceFromUri **Material 3 ImageButton test cases:** - VerifyMaterial3ImageButtonAspect_AspectFillWithImageSourceFromUri - VerifyMaterial3ImageButtonAspect_AspectFillWithImageSourceFromFile - VerifyMaterial3ImageButtonAspect_CenterWithImageSourceFromUri Validated the behavior in the following platforms - [x] Android - [ ] Mac - [ ] iOS - [ ] Windows ### Issues Fixed Fixes #29956 ### Output ScreenShot |Platform|Before|After| |--|--|--| |Android|<video src="https://github.com/user-attachments/assets/d8c08b97-8de2-4af0-8773-46a1e376bbbc">|<video src="https://github.com/user-attachments/assets/fb3c6814-acd2-4688-8d12-e691245a44e0">| --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
…39525) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change <!-- Enter description of the fix in this section --> The Windows CollectionView handler creates a managed `GroupHeaderStyleSelector` whenever the item template is updated, including during layout changes. Post-GC heap snapshots show these selector instances accumulating after CollectionViews are removed or their pages are popped. The selector ignores the group and nesting level and always returns a `GroupStyle` using the same header template. Replace this managed WinRT callback with a native `GroupStyle` configured directly on the control, and remove the unused selector class. Replace the existing style on subsequent updates so styles do not accumulate. Add Windows regression coverage for grouped and ungrouped collections, repeated template updates, list/grid layout changes, group header/footer rendering, and switching grouping off and on. Fixed #32403 — addresses the GroupHeaderStyleSelector accumulation reported in the comment Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…bounds (#39561) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change Fix popup alignment reported after upgrading Microsoft.Maui.Controls from 10.0.110 to 10.0.120. The margin-overflow logic in LayoutExtensions clamps negative alignment space even when the margins themselves fit within the available bounds. When content plus margins exceeds those bounds, this suppresses the offset needed for centering and shifts the popup toward the trailing edge. This change: - Restricts horizontal and vertical alignment clamping to cases where the margins consume all available space. - Preserves the existing large-margin correction and FlexLayout exception. - Adds regression coverage for Center, End, and explicitly sized Fill alignment, plus margin-overflow and FlexLayout preservation cases. Regression PR #37080 ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #39557 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
#39486) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Issue Details - When IsRefreshEnabled="false" is set on a RefreshView, the pull-to-refresh gesture remains active on iOS and macOS, allowing the content to be pulled down even though the refresh indicator is not displayed and the Refreshing event is not triggered. ### Root Cause - MauiRefreshView sets UIScrollView.AlwaysBounceVertical to true when attaching UIRefreshControl, so the user can pull the content to trigger refresh. However, when IsRefreshEnabled is set to false, MAUI removes the UIRefreshControl but does not restore the scroll view's original AlwaysBounceVertical value. As a result, the UIScrollView remains vertically pullable even though the refresh control has been removed. ### Description of Change - MauiRefreshView now stores the original value of AlwaysBounceVertical before enabling refresh, and restores it only if it hasn't been changed elsewhere when disabling refresh. This prevents unintended side effects when toggling refresh or replacing scroll views. ### Issues Fixed Fixes #39080 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Platform | Before | After | |----------|----------|----------| | iOS | <video src="https://github.com/user-attachments/assets/56070801-4357-4e94-9a1d-c8b3ed0d3125"> | <video src="https://github.com/user-attachments/assets/f2dbe2cb-2c58-4b5c-8c5f-c4d4bd6f409b"> | | Mac | <video src="https://github.com/user-attachments/assets/6a4f6b2a-9a8c-4886-96ae-6514f1b2c844"> | <video src="https://github.com/user-attachments/assets/292ee1c6-1b79-46a5-bd0a-f13a3848d1dc"> |
) ### Issue - While running `Controls.DeviceTests` on Android, the build fails with the `xUnit2031` analyzer error. ### Description - Updates the Android `SwipeView` device test in `SwipeViewTests.Android.cs` to use the `Assert.Single` overload that accepts a predicate. - This resolves the `xUnit2031` analyzer error caused by using a `Where` clause to filter a collection before calling `Assert.Single`. - **Reference:** https://xunit.net/xunit.analyzers/rules/xUnit2031 ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #39376 | Before | After | |----------|----------| | <img src="https://github.com/user-attachments/assets/fb0e0455-9b80-433f-bb78-80cbe499d600"> | <img src="https://github.com/user-attachments/assets/595fe45a-aca4-4dd7-b65b-1ce5c8642d1b"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
On Android a ContentView or Border kept the full height of its content after we set the content to IsVisible=false. In our app that left a hidden card at 576 dp and the page two thirds empty. On Windows the same layout collapses fine. MeasureContent measures the content no matter if it's visible. WinUI returns 0 for a collapsed element, but Android measures a GONE view at its full size. The layout managers already skip collapsed children, so I did the same in both MeasureContent overloads and added a unit test for it. Right now we hide the wrapper instead of the content. <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes # <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
#39595) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change <!-- Enter description of the fix in this section --> Backports [#38911](#38911), squash commit `37045aab7a4700a5de982ad4647e14a15b27f2c9`, from `net11.0` to **`inflight/current`**, as explicitly requested. Uses the owning window's geometry for the iOS 26 Stepper landscape compensation, the effective view scale for safe-area pixel comparisons, and the owning window-scene display scale for bitmap rendering. Detached views retain the main-screen fallback. Includes the original regression tests; no public API changes. The cherry-pick applied without conflicts or target-specific adaptations, preserving the original author. Source and backport stable patch IDs both equal `9a3c3feabcc820e6c510853169982b9797b2efb9`. No equivalent open or recently merged backport was found before publishing. **Validation performed on this backport:** - `git diff --cached --check` and `git diff --check` — passed before committing. - `dotnet format Microsoft.Maui.sln --no-restore --exclude Templates/src --exclude-diagnostics CA1822 --include $(git diff --cached --name-only)` — exited 0 and made no changes, but reported missing references for Core, Controls.Core and Core.DeviceTests on iOS/MacCatalyst. This is not a successful semantic-formatting or compilation claim. - `dotnet format whitespace --folder --include $(git diff --cached --name-only) --verify-no-changes` — passed. - `./build.sh -restore -build -configuration Release -projects "$PWD/Microsoft.Maui.BuildTasks.slnf" /bl:/Users/kubaflo/.copilot/session-state/2cf9c397-ac62-41d3-b41c-3d5bd2ba5242/files/BuildBuildTasks.binlog -warnAsError false` — attempted, then stopped during pinned SDK/workload bootstrapping; no completed build result. The separate solution-based whitespace verification was also stopped during workspace loading; the folder-based check above completed successfully. Runtime/device/UI tests were **not run** for this backport. No XCTest or host UI automation was used. Source-PR validation results are not presented as new backport results. Target-branch CI remains required. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Backport of [#38911](#38911). <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change <!-- Enter description of the fix in this section --> Backports [#38915](#38915), "Add iPhone Duo support to Controls.Foldable", from squash commit `a561eaec4aacbe962416c64491aa5ffbc6bde9ae` to **`inflight/current`**, as explicitly requested. Preserves the source implementation: view/window-scoped reserved-region geometry, hinge monitoring and lifecycle cleanup, scene activation support, shared layout refresh, state triggers, sample updates, and Foldable unit tests. Original author and source coauthors are preserved. The only cherry-pick conflicts were in `.github/scripts/RunTests.ps1` and `.github/scripts/shared/Detect-TestsInDiff.ps1`. Resolution retains this branch's Compatibility test entries and adds the source Foldable mappings. Formatting is scoped to changed C# files; the formatter's unrelated Android null-conditional event rewrite was not retained. **SDK limitation:** the source's native Duo path is enabled only for iOS target platform version 27.1+ (or an explicit `IosDuoBindingsAvailable` override with compatible bindings). This target branch currently defaults to iOS 26.0, so its default build retains fallback behavior rather than enabling Duo APIs. This PR does not upgrade the branch-wide SDK/workload or remove capability/runtime guards. Publishing actual Duo-enabled artifacts requires a compatible iOS 27.1 SDK build configuration. **Validation run in this backport worktree** using .NET SDK `11.0.100-preview.6.26359.118`, targeting this branch's `net10.0` TFMs, and Xcode 26.6: | Command | Result | | --- | --- | | `dotnet test src/Controls/Foldable/test/Controls.Foldable.UnitTests.csproj --nologo --verbosity minimal` | Passed: 39, failed: 0, skipped: 0; rerun after formatting and normal restore. | | `dotnet build src/Controls/Foldable/src/Controls.Foldable.csproj -f net10.0-ios26.0 --nologo --verbosity minimal` | Passed: 0 warnings, 0 errors. | | `dotnet build src/Controls/Foldable/src/Controls.Foldable.csproj -f net10.0-maccatalyst26.0 --no-restore --nologo --verbosity minimal` | Passed: 0 warnings, 0 errors. | | `dotnet build src/Controls/Foldable/src/Controls.Foldable.csproj -f net10.0-android36.0 --no-restore --nologo --verbosity minimal` | Passed: 3 Gradle Java 8 obsolescence warnings, 0 errors. | | `dotnet build src/Controls/Foldable/src/Controls.Foldable.csproj -f net10.0-ios27.1 -p:TargetFrameworks=net10.0-ios27.1 --nologo --verbosity minimal` | Blocked: NETSDK1140, local SDK supports iOS 26.0/26.5, not 27.1. | | `git diff --cached --check` | Passed. | | `git diff --check` | Passed. | Formatting command (passed; `changed_files` contains staged changed `.cs` paths): ```bash changed_files=() while IFS= read -r file; do changed_files+=("$file"); done < <(git diff --cached --name-only -- '*.cs') dotnet format Microsoft.Maui.sln --no-restore --exclude Templates/src --exclude-diagnostics CA1822 --include "${changed_files[@]}" --verbosity quiet ``` PowerShell syntax check (passed for all three source script files): ```powershell $files=@(".github/scripts/RunTests.ps1", ".github/scripts/shared/Detect-TestsInDiff.ps1", ".github/scripts/shared/Detect-TestsInDiff.Tests.ps1") foreach ($file in $files) { $tokens=$null; $errors=$null [System.Management.Automation.Language.Parser]::ParseFile((Join-Path $PWD $file), [ref]$tokens, [ref]$errors) > $null if ($errors.Count) { $errors | Write-Error; exit 1 } Write-Output "Parsed $file" } ``` Build/test/format subprocesses ran with `GH_TOKEN`, `GITHUB_TOKEN`, and `COPILOT_GITHUB_TOKEN` removed from their environments. A `--no-restore` test attempt after the explicit 27.1 restore probe encountered changed assets; normal restore and the full 39-test rerun above succeeded. **Not run:** native iOS 27.1/Duo compilation or simulator/device runtime validation, sample app build/runtime validation, Windows validation, or pipeline Pester tests. No XCTest or host UI automation was used. Source PR validation is not claimed as a result of this backport. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Backport of [#38915](#38915); no separate issue. <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 741e14bf-fe5c-4150-857c-40b354de3403
Contributor
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 29755Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 29755" |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This branch had an error being deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.