Skip to content

Fix SwipeView Threshold changes width and offset of the side menu (when visible)#34923

Open
KarthikRajaKalaimani wants to merge 9 commits intodotnet:mainfrom
KarthikRajaKalaimani:fix-6016
Open

Fix SwipeView Threshold changes width and offset of the side menu (when visible)#34923
KarthikRajaKalaimani wants to merge 9 commits intodotnet:mainfrom
KarthikRajaKalaimani:fix-6016

Conversation

@KarthikRajaKalaimani
Copy link
Copy Markdown
Contributor

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 from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details:

SwipeView Threshold changes width and offset of the side menu (when visible) Opened.

Root Cause:

The SwipeView.Threshold property is designed for a single purpose: setting the minimum drag distance a user must swipe before the menu snaps open. It has nothing to do with how wide the menu
items should appear or where the content settles after the swipe. However, the platform code on both iOS and Android was incorrectly using this value in two unrelated calculations.

The first misuse was in GetSwipeItemSize(), where the code checked if Threshold > 0 and, if so, used the threshold value as the item's width. This meant that setting Threshold=200 would inflate
every swipe item to 200pt wide, far larger than the intended ~100pt. The second misuse was in GetSwipeThreshold(ISwipeItems), which had an early return that directly handed back the Threshold
value as the snap-open distance. So the content would snap to 200pt offset instead of snapping to the actual menu width. Together, these two bugs caused both the menu to look bloated and the
content displacement to differ depending on whether Threshold was set.

Description of Change:

The fix removes Threshold from both of those calculations entirely. Item sizing now uses only the item's configured WidthRequest or the default SwipeItemWidth, as it should. The snap distance is now computed as Math.Min(Threshold, menuWidth) — meaning if Threshold is set, it acts as a cap on how far the user needs to drag, but the content still snaps to the true menu width. If Threshold is not set, the default behaviour of 60% of menu width is preserved. This was applied consistently across iOS (MauiSwipeView.cs and SwipeViewExtensions.cs) and Android (MauiSwipeView.cs).

Tested the behavior in the following platforms:

  • Android
  • Windows
  • iOS
  • Mac

Reference:

N/A

Issues Fixed:

Fixes #6016

Screenshots

Before After
Before_fix_6016.mov
After_fix_6016.mov

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 13, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34923

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34923"

@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Apr 13, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Hey there @@KarthikRajaKalaimani! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Apr 13, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review April 13, 2026 10:11
Copilot AI review requested due to automatic review settings April 13, 2026 10:11
@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes incorrect use of SwipeView.Threshold in the iOS and Android platform implementations so that Threshold affects only the trigger distance for opening, not the rendered swipe menu width or the final open offset.

Changes:

  • iOS/Android: stop using Threshold to size swipe items and to determine the open snap distance; compute open distance from actual menu size and treat Threshold as a cap for the trigger distance.
  • iOS/Android: rename internal “threshold” helper to reflect “open distance” semantics and update call sites.
  • Add a new UI test page + Appium test for Issue 6016 to validate menu width is unaffected by Threshold and that Execute mode still triggers.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Core/src/Platform/iOS/SwipeViewExtensions.cs Removes Threshold from swipe-item sizing calculations on iOS.
src/Core/src/Platform/iOS/MauiSwipeView.cs Uses menu open distance for snapping; uses Threshold only for trigger distance on iOS.
src/Core/src/Platform/Android/MauiSwipeView.cs Mirrors iOS behavior changes on Android; removes old reveal-threshold helper and stops sizing by Threshold.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue6016.cs Adds Appium UI coverage for the regression (menu width/offset + Execute mode).
src/Controls/tests/TestCases.HostApp/Issues/Issue6016.cs Adds HostApp reproduction page used by the new UI test.

Comment thread src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue6016.cs
Comment thread src/Core/src/Platform/iOS/MauiSwipeView.cs
Comment thread src/Core/src/Platform/Android/MauiSwipeView.cs
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Apr 13, 2026
@KarthikRajaKalaimani
Copy link
Copy Markdown
Contributor Author

🤖 AI Summary

👋 @KarthikRajaKalaimani — new AI review results are available. Please review the latest session below.

📊 Review Session2cf3f8e · Test case removed for windows platform · 2026-04-13 13:25 UTC
🔍 Pre-Flight — Context & Validation
Issue: #6016 - SwipeView Threshold changes width and offset of the side menu (when visible) PR: #34923 - Fix SwipeView Threshold changes width and offset of the side menu (when visible) Platforms Affected: Android (primary), iOS, macCatalyst (fix applied to both) Files Changed: 3 implementation, 2 test

Key Findings

  • Bug: GetSwipeThreshold() incorrectly used Element.Threshold as both item width AND snap distance, so setting Threshold=200 caused 200dp-wide menu items and 200dp content displacement instead of the intended ~100dp defaults.
  • Root cause (Android): GetSwipeItemSize() used threshold > 0 ? threshold : SwipeItemWidth for item width; GetSwipeThreshold(ISwipeItems) had early return if (threshold > 0) return threshold for snap distance.
  • Root cause (iOS): Same dual misuse in GetSwipeItemSize() (SwipeViewExtensions.cs) and GetSwipeThreshold(ISwipeItems) (MauiSwipeView.cs).
  • PR's fix: Renames GetSwipeThresholdGetSwipeOpenDistance (computes menu width only); ValidateSwipeThreshold now uses Min(Threshold, menuWidth) as trigger threshold if Threshold > 0, else 60% * menuWidth.
  • Gate: Without fix test FAILED correctly (proves bug exists). With fix got ENV ERROR — PowerShell regex match on null input in gate script, not a test failure; timing/infrastructure issue, not a code correctness issue.
  • Review comments (prior agent): WaitForXPosition doesn't assert on timeout (silent wrong X); _swipeThreshold field name misleading after rename; same on Android.
  • Test file wraps entire file in #if TEST_FAILS_ON_WINDOWS but [Issue] specifies PlatformAffected.Android — inconsistency; test should run on Android and iOS, not just non-Windows.
  • WaitForTextToBePresentInElement used in SwipeViewExecuteModeTriggers — need to confirm this API exists.

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #34923 Remove Threshold from item sizing; rename to GetSwipeOpenDistance; trigger = Min(Threshold, menuWidth) ⚠️ ENV ERROR (Gate infra issue, not fix correctness) Android/MauiSwipeView.cs, iOS/MauiSwipeView.cs, iOS/SwipeViewExtensions.cs Original PR
🔧 Fix — Analysis & Comparison

Fix Candidates

Source Approach Test Result Files Changed Notes

1 try-fix (opus-4.6) Add GetMenuOpenDistance(ISwipeItems) helper; keeps existing method names; Android only ✅ PASS Android/MauiSwipeView.cs Clean separation, minimal call-site changes
2 try-fix (sonnet-4.6) Inline removal — no new helpers/renames, remove early-return + threshold from sizing, Min(Threshold,menuWidth) trigger; Android only ✅ PASS Android/MauiSwipeView.cs Smallest possible change
3 try-fix (codex) Add GetSnapOpenDistance cache field separate from trigger; iOS+Android ✅ PASS (Android; iOS unverified) iOS/MauiSwipeView.cs, iOS/SwipeViewExtensions.cs, Android/MauiSwipeView.cs Cross-platform but iOS not tested
4 try-fix (gpt-5.4) Harden test: TryWaitForXPosition returns (bool satisfied, float x), callers assert satisfaction; test-only fix ✅ PASS TestCases.Shared.Tests/Tests/Issues/Issue6016.cs Eliminates silent false-positive; Execute-mode API valid
PR PR #34923 Rename GetSwipeThreshold to GetSwipeOpenDistance; remove Threshold from sizing; Min(Threshold,menuWidth) trigger; iOS+Android ⚠️ ENV ERROR (gate infra, not fix correctness) iOS/MauiSwipeView.cs, iOS/SwipeViewExtensions.cs, Android/MauiSwipeView.cs Original PR; cross-platform; semantically clearest rename

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 NO NEW IDEAS Attempt 1 helper approach already complete for Android
claude-sonnet-4.6 2 YES Combine minimal platform fix (Attempt 2) + Attempt 4 test hardening
gpt-5.3-codex 2 NO NEW IDEAS Attempt 3 cross-platform already covered
gpt-5.4 2 YES Apply PR rename (most descriptive) + Attempt 4 test hardening together
Exhausted: Yes — all 4 models queried, 2 rounds completed Selected Fix: PR's fix + Attempt 4 test hardening — PR rename is most semantically clear (GetSwipeOpenDistance vs GetSwipeThreshold), covers iOS+Android, and the Gate's "without fix" phase confirmed the bug is real. Attempt 4 test hardening eliminates silent false-positives and should be incorporated.

📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #6016, SwipeView Threshold bug on Android/iOS
Gate ❌ FAILED Without fix: ✅ FAIL (bug confirmed). With fix: ⚠️ ENV ERROR (gate infra null-input regex — not fix correctness)
Try-Fix ✅ COMPLETE 4 attempts, 4 passing; gemini unavailable (gpt-5.4 used)
Report ✅ COMPLETE

Summary

PR #34923 fixes a real bug (confirmed by Gate's "without fix" run) where SwipeView.Threshold incorrectly controlled both menu item width and content snap distance. The platform logic fix is sound and all 4 independent Try-Fix explorations confirmed the root cause and a correct fix strategy. However, the PR's test has a silent-failure bug (WaitForXPosition doesn't assert predicate satisfaction), and several issues found by the prior code review remain unaddressed. The Gate ENV ERROR is an infrastructure issue, not a correctness failure in the fix itself.

Root Cause

Two misuses of Element.Threshold in both Android and iOS MauiSwipeView:

  1. GetSwipeItemSize() — used threshold > 0 ? threshold : SwipeItemWidth as item width, inflating menu items to Threshold dp wide.
  2. GetSwipeThreshold(ISwipeItems) — had an early return if (threshold > 0) return threshold, so content snapped to Threshold dp offset instead of actual menu width.

Fix Quality

Platform fix (Android/iOS MauiSwipeView.cs + SwipeViewExtensions.cs): Correct. Removes Threshold from item sizing (always uses SwipeItemWidth), removes early-return from menu-width computation, applies Threshold only as a trigger cap: triggerThreshold = Min(Threshold, menuWidth) (or 60%*menuWidth if unset). All 4 independent Try-Fix models confirmed this approach.

Test (Issue6016.cs): Has actionable defects that should be fixed before merge:

  1. WaitForXPosition silent failure — Returns last observed X regardless of whether the predicate was satisfied. If a swipe gesture silently fails (content didn't move), defaultMenuWidth and thresholdMenuWidth both equal 0, and Assert.That(0, Is.EqualTo(0).Within(5)) passes falsely. Try-Fix Attempt 4 provides a tested fix: rename to TryWaitForXPosition, return bool satisfied, callers assert Is.True.
  2. _swipeThreshold field name misleading — The field now caches computed open distance (menu width/height), not the trigger threshold. Identified in prior code review. Should be renamed _swipeOpenDistance in both Android and iOS MauiSwipeView.cs to match GetSwipeOpenDistance.
  3. Missing newline at EOFIssue6016.cs (tests) is missing a final newline.
  4. #if TEST_FAILS_ON_WINDOWS scope vs PlatformAffected.Android — HostApp [Issue] declares PlatformAffected.Android but the entire test file is wrapped in #if TEST_FAILS_ON_WINDOWS, which would also run on iOS/macCatalyst. Either align the [Issue] attribute to PlatformAffected.All (minus Windows) or add an explicit [Platform] filter in the test.

Required Changes Before Merge

  • Fix WaitForXPositionTryWaitForXPosition (assert predicate satisfaction) per Try-Fix Attempt 4 diff
  • Rename _swipeThreshold_swipeOpenDistance in both Android/MauiSwipeView.cs and iOS/MauiSwipeView.cs
  • Add newline at end of TestCases.Shared.Tests/Tests/Issues/Issue6016.cs
  • Align PlatformAffected attribute with actual test platform scope

addressed AI summary concerns

@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Apr 17, 2026

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Looks like some tests are failing - could you please verify?

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

PureWeen pushed a commit that referenced this pull request Apr 30, 2026
…ability (#35133)

<!-- 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!

> **Depends on #35136** (pipeline category detection — should merge
first)

## What this does

Two things:

### 1. UI test category detection in PR review

During the PR review workflow, Step 0.5 detects which UI test categories
the PR impacts and writes the result to the AI summary comment. This
gives reviewers visibility into which UI tests are relevant.

**Detection** reuses the 3-tier script from #35136 (test attributes →
source paths → AI reasoning).

**AI summary** shows a new 🧪 UI Tests section with detected categories
before the gate section.

### 2. Gate reliability fixes

Multiple fixes to make the gate (`verify-tests-fail.ps1`) more
deterministic:

| Fix | Problem it solves |
|-----|-------------------|
| **Absolute path resolution** | Gate scripts not found on Linux CI
agents (`Resolve-Path`, `GetFullPath`) |
| **File existence check** | Instant cryptic failure when verify script
is missing — now logs clear error |
| **3x retry on ENV ERROR** | Emulator timeouts, ADB failures, app
crashes — transient issues that pass on retry |
| **Strip bad report blocks** | Old verify script produces `Passed:
False` with empty counts — stripped instead of shown |
| **Gate log in fallback** | When report is missing, shows last 20 lines
of gate output instead of just `❌ FAILED / Platform: IOS` |

## Files

| File | Changes |
|------|---------|
| `.github/scripts/Review-PR.ps1` | Step 0.5 category detection + all 5
gate fixes |
| `.github/scripts/post-ai-summary-comment.ps1` | Add `uitests` phase to
render detected categories |
| `.github/pr-review/pr-preflight.md` | Step 7: AI identifies impacted
UI test categories |

## Validation — PR reviewer builds (Apr 26)

10 builds against real PRs — all succeeded ✅. Category detection shown
in AI summary comment.

| PR | Categories Detected | Build | AI Summary |
|----|-------------------|-------|------------|
| #35037 (WebView theme) | `ViewBaseTests,WebView` |
[13940071](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940071)
|
[comment](#35037 (comment))
|
| #35031 (Shell memory leak) | `Shell` |
[13940072](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940072)
|
[comment](#35031 (comment))
|
| #35020 (XAML Hot Reload) | _(none — XAML only)_ |
[13940073](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940073)
| ✅ Shows "No UI test categories" |
| #35008 (Shell SearchHandler) | `Shell` |
[13940074](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940074)
| ✅ |
| #34997 (RadioButton gradient) | `RadioButton,ViewBaseTests` |
[13940075](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940075)
| ✅ |
| #34980 (DatePicker rotation) | `ViewBaseTests` |
[13940076](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940076)
| ✅ |
| #34974 (Picker CharacterSpacing) | `ViewBaseTests` |
[13940077](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940077)
| ✅ |
| #34923 (SwipeView threshold) | `SwipeView,ViewBaseTests` |
[13940078](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940078)
| ✅ |
| #34907 (CollectionView ScrollTo) | `CollectionView` |
[13940079](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940079)
| ✅ |
| #34845 (RefreshView binding) | `RefreshView,ViewBaseTests` |
[13940080](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940080)
| ✅ |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet dotnet deleted a comment from MauiBot May 2, 2026
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

Choose a reason for hiding this comment

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

Expert Review — 7 findings

See inline comments for details.

@dotnet dotnet deleted a comment from MauiBot May 3, 2026
@dotnet dotnet deleted a comment from MauiBot May 3, 2026
@dotnet dotnet deleted a comment from MauiBot May 3, 2026
@dotnet dotnet deleted a comment from MauiBot May 3, 2026
@dotnet dotnet deleted a comment from MauiBot May 3, 2026
@dotnet dotnet deleted a comment from MauiBot May 3, 2026
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

Choose a reason for hiding this comment

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

Expert Review — 3 findings

See inline comments for details.

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Some swipe view tests are failing - could you please verify?

@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

Choose a reason for hiding this comment

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

Expert Review — 7 findings

See inline comments for details.

@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented May 7, 2026

🤖 AI Summary

👋 @KarthikRajaKalaimani — new AI review results are available. Please review the latest session below.

📊 Review Sessionb7df93e · Snapshot updated · 2026-05-07 22:34 UTC
🚦 Gate — Test Before & After Fix

Gate Result: ✅ PASSED

Platform: ANDROID · Base: main · Merge base: b71adea6

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue6016 Issue6016 ✅ FAIL — 562s ✅ PASS — 518s
🔴 Without fix — 🖥️ Issue6016: FAIL ✅ · 562s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
  Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:07:00.22
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.11]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.31]   Discovered:  Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
   NUnit3TestExecutor discovered 3 of 3 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 05/07/2026 22:19:28 FixtureSetup for Issue6016(Android)
>>>>> 05/07/2026 22:19:30 SwipeViewThresholdShouldNotChangeMenuWidth Start
>>>>> 05/07/2026 22:19:35 SwipeViewThresholdShouldNotChangeMenuWidth Stop
>>>>> 05/07/2026 22:19:35 Log types: logcat, bugreport, server
  Failed LeftItems [5 s]
  Error Message:
     SwipeView menu width should not change with Threshold. Default=263.0px, Threshold=200 → 478.0px
Assert.That(thresholdMenuWidth, Is.EqualTo(defaultMenuWidth).Within(5))
  Expected: 263.0f +/- 5
  But was:  478.0f
  Off by:   -215.0d

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.Issues.Issue6016.SwipeViewThresholdShouldNotChangeMenuWidth(String defaultContentId, String thresholdContentId, String defaultSwipeViewId, String thresholdSwipeViewId, Boolean swipeRight) in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue6016.cs:line 77

1)    at Microsoft.Maui.TestCases.Tests.Issues.Issue6016.SwipeViewThresholdShouldNotChangeMenuWidth(String defaultContentId, String thresholdContentId, String defaultSwipeViewId, String thresholdSwipeViewId, Boolean swipeRight) in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue6016.cs:line 77


>>>>> 05/07/2026 22:19:36 SwipeViewThresholdShouldNotChangeMenuWidth Start
>>>>> 05/07/2026 22:19:39 SwipeViewThresholdShouldNotChangeMenuWidth Stop
>>>>> 05/07/2026 22:19:39 Log types: logcat, bugreport, server
  Failed RightItems [3 s]
  Error Message:
     SwipeView menu width should not change with Threshold. Default=263.0px, Threshold=200 → 314.0px
Assert.That(thresholdMenuWidth, Is.EqualTo(defaultMenuWidth).Within(5))
  Expected: 263.0f +/- 5
  But was:  314.0f
  Off by:   -51.0d

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.Issues.Issue6016.SwipeViewThresholdShouldNotChangeMenuWidth(String defaultContentId, String thresholdContentId, String defaultSwipeViewId, String thresholdSwipeViewId, Boolean swipeRight) in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue6016.cs:line 77
   at InvokeStub_Issue6016.SwipeViewThresholdShouldNotChangeMenuWidth(Object, Span`1)

1)    at Microsoft.Maui.TestCases.Tests.Issues.Issue6016.SwipeViewThresholdShouldNotChangeMenuWidth(String defaultContentId, String thresholdContentId, String defaultSwipeViewId, String thresholdSwipeViewId, Boolean swipeRight) in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue6016.cs:line 77
   at InvokeStub_Issue6016.SwipeViewThresholdShouldNotChangeMenuWidth(Object, Span`1)


>>>>> 05/07/2026 22:19:39 SwipeViewExecuteModeTriggers Start
>>>>> 05/07/2026 22:19:41 SwipeViewExecuteModeTriggers Stop
  Passed SwipeViewExecuteModeTriggers [1 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Failed.
Total tests: 3
     Passed: 1
     Failed: 2
 Total time: 26.1893 Seconds

🟢 With fix — 🖥️ Issue6016: PASS ✅ · 518s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
  Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:06:41.75
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042758
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.11]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.32]   Discovered:  Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
   NUnit3TestExecutor discovered 3 of 3 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 05/07/2026 22:28:09 FixtureSetup for Issue6016(Android)
>>>>> 05/07/2026 22:28:11 SwipeViewThresholdShouldNotChangeMenuWidth Start
>>>>> 05/07/2026 22:28:15 SwipeViewThresholdShouldNotChangeMenuWidth Stop
  Passed LeftItems [3 s]
>>>>> 05/07/2026 22:28:15 SwipeViewThresholdShouldNotChangeMenuWidth Start
>>>>> 05/07/2026 22:28:18 SwipeViewThresholdShouldNotChangeMenuWidth Stop
  Passed RightItems [3 s]
>>>>> 05/07/2026 22:28:18 SwipeViewExecuteModeTriggers Start
>>>>> 05/07/2026 22:28:20 SwipeViewExecuteModeTriggers Stop
  Passed SwipeViewExecuteModeTriggers [1 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 3
     Passed: 3
 Total time: 22.1514 Seconds

📁 Fix files reverted (3 files)
  • src/Core/src/Platform/Android/MauiSwipeView.cs
  • src/Core/src/Platform/iOS/MauiSwipeView.cs
  • src/Core/src/Platform/iOS/SwipeViewExtensions.cs

🧪 UI Tests — Category Detection

Detected UI test categories: SwipeView,ViewBaseTests

🧪 UI Test Execution Results

FAILED — 1 passed, 1 failed, 0 skipped (platform: android)

Category Result Duration Notes
SwipeView ❌ FAILED 2064.8s exit code 1
ViewBaseTests ✅ PASSED 1001.6s

Failures here are informational only — they do not block the gate or affect try-fix candidate scoring.


🔍 Regression Cross-Reference

🔍 Regression Cross-Reference

🟢 No regression risks detected. No labeled bug-fix PRs in the last 6 months touched the modified files.


🔍 Pre-Flight — Context & Validation

Issue: #6016 - SwipeView Threshold changes width and offset of the side menu (when visible)
PR: #34923 - Fix SwipeView Threshold changes width and offset of the side menu (when visible)
Platforms Affected: Android, iOS (MacCatalyst inherits via .ios.cs)
Files Changed: 3 implementation (src/Core/src/Platform/Android/MauiSwipeView.cs, src/Core/src/Platform/iOS/MauiSwipeView.cs, src/Core/src/Platform/iOS/SwipeViewExtensions.cs), 2 test (Issue6016.cs HostApp + Shared.Tests), plus 12 snapshot baselines updated.

Key Findings

  • SwipeView.Threshold is documented as the minimum drag distance needed to snap-open the menu, but the platform code conflated it with two unrelated quantities: (a) the swipe-item display width (GetSwipeItemSize), and (b) the snap-open distance (GetSwipeThreshold(ISwipeItems)).
  • The PR removes both misuses. Item size now uses WidthRequest or SwipeViewExtensions.SwipeItemWidth (default 100). Snap distance is computed purely from the menu width. The user-set Threshold is now used only as a cap on the trigger threshold: triggerThreshold = Element.Threshold > 0 ? Math.Min(Threshold, openDistance) : 0.6 * openDistance.
  • Renames are part of the change: field _swipeThreshold_swipeOpenDistance; helper GetSwipeThreshold() / GetSwipeThreshold(ISwipeItems)GetSwipeOpenDistance(...). Android also drops the now-unused GetRevealModeSwipeThreshold().
  • 12 PNG snapshot baselines were regenerated because both Android and iOS-26 visual diffs now show the corrected (non-bloated) menu width.
  • Tests added for two parameterized cases (LeftItems / RightItems) plus an Execute-mode regression guard. Test is gated #if TEST_FAILS_ON_WINDOWS because SwipeItem AutomationId isn't propagated on Windows.
  • Inline reviewer (Copilot) feedback on the PR raised two concerns: (1) WaitForXPosition silently returns the last X on timeout — the test could pass with both menu widths == 0; consider failing on timeout. (2) The field name _swipeThreshold was misleading after semantics changed (already addressed by the rename in this PR; the inline comment was authored on an older revision).
  • Gate result: ✅ PASSED (test fails on baseline, passes with fix).

Code Review Summary

Verdict: NEEDS_CHANGES (low-severity)
Confidence: medium
Errors: 0 | Warnings: 2 | Suggestions: 3

Key code review findings:

  • ⚠️ src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue6016.cs:33WaitForXPosition swallows timeout: it returns the last observed X without asserting the predicate ever became true, so a swipe that fails to register can still produce defaultMenuWidth == thresholdMenuWidth == 0, and the equality assertion will spuriously pass. Recommend asserting predicate satisfaction (or returning a (bool satisfied, float x) tuple) before computing widths.
  • ⚠️ src/Core/src/Platform/Android/MauiSwipeView.cs:993-998 and src/Core/src/Platform/iOS/MauiSwipeView.cs:765-772 — duplicated trigger-threshold logic across Android and iOS. The block if (Element != null && Element.Threshold > 0) triggerThreshold = Math.Min(Threshold, openDistance) else 0.6 * openDistance appears 2× on Android (ProcessTouchUp + RaiseSwipeEnded) and 1× on iOS. Consider extracting GetTriggerThreshold() to keep the two platforms in sync.
  • 💡 Element != null && Element.Threshold > 0 — on Android Element is repeatedly null-checked elsewhere; consider caching or using local var to avoid double-deref between branches.
  • 💡 The local triggerThreshold clamps to Math.Min(Threshold, openDistance). If Threshold is set very low (e.g., 5dp), the menu still snaps to full open distance, but the user-perceived "trigger" is reasonable. Consider also enforcing a minimum of MinimumOpenSwipeThresholdPercentage * openDistance on iOS to keep the existing 15% floor.
  • 💡 Math.Abs(_swipeOpenDistance) > double.Epsilon — the cache check is unchanged, but reads slightly oddly when the value is conceptually a distance (always ≥ 0). Could simplify to _swipeOpenDistance > 0.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #34923 Remove Threshold from item-size + snap-distance; use Threshold as a min(Threshold, openDistance) cap on trigger; rename field/methods ✅ PASSED (Gate) 3 src + 2 test + 12 snapshots Original PR

🔧 Fix — Analysis & Comparison

Try-Fix Summary (4 candidates)

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix-1 (claude-opus-4.6) Split into GetSwipeThreshold() (trigger) + GetSwipeOpenDistance() (snap distance); reuse old method name with new semantics ⏳ Not validated; logically equivalent to PR 3 src + tests + 12 snapshots Symbol-name churn for no behaviour change
2 try-fix-2 (claude-sonnet-4.6) PR fix + extract GetTriggerThreshold() helper to dedupe Android/iOS trigger logic ⏳ Not validated; pure refactor on top of PR PR's files + ~10 lines Nice cleanup; better as follow-up PR
3 try-fix-3 (gpt-5.3-codex) PR fix + cache _triggerThreshold for hot-path optimization ⏳ Not validated; introduces stale-cache risk for bound Threshold PR's files + ~24 lines Likely regression on bound Threshold mutations
4 try-fix-4 (gemini-3-pro-preview) Minimal: only delete the 2 misuses; do not add Math.Min(Threshold, openDistance) cap; no renames ❌ Loses Threshold-as-trigger-cap feature; users wanting "less sensitive" swipe regress smaller delta in src + tests + 12 snapshots Drops a useful behaviour PR adds
PR PR #34923 Remove Threshold from item-size + snap-distance; cap trigger via Math.Min(Threshold, openDistance) else 60%; rename field/methods ✅ PASSED (Gate) 3 src + 2 test + 12 snapshots Original PR — gate-verified

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 NO NEW IDEAS The PR's approach already covers the substantive fix; remaining variations are stylistic.
claude-sonnet-4.6 2 NO NEW IDEAS Refactor proposal (try-fix-2) stands as-is.
gpt-5.3-codex 2 NO NEW IDEAS Caching idea (try-fix-3) carries regression risk; declines further variants.
gemini-3-pro-preview 2 NO NEW IDEAS Conservative variant (try-fix-4) drops a feature; declines further variants.

Exhausted: Yes
Selected Fix: PR #34923 + reviewer test-quality fix (pr-plus-reviewer) — the PR is gate-verified
and is the only candidate explicitly tested. The expert reviewer surfaced one real test-quality
bug (silent timeout in WaitForXPosition) which pr-plus-reviewer addresses without altering any
production code.

Environment note

Try-fix candidates were generated and analyzed but not built/run because the agent's environment
(Linux without an Android emulator) cannot execute BuildAndRunHostApp.ps1 for Android UI tests.
The PR's gate result (✅ test fails on baseline, passes with fix) is the only empirical signal
available; per the prompt rules, candidates without passing test results MUST rank below the PR.


📋 Report — Final Recommendation

Final Recommendation — PR #34923

Phase Status
Gate ✅ PASSED — tests fail on baseline, pass with fix
Pre-Flight ✅ Complete
Code Review ✅ Complete (NEEDS_CHANGES, low-severity — 2 warnings, 3 suggestions)
Try-Fix ×4 ✅ Complete (4 candidates analysed)
Report ✅ Complete

Comparative analysis

Candidate Gate-tested Behavioural delta vs PR Risk Rank
pr (baseline) Low 2
pr-plus-reviewer ✅ (PR's gate; sandbox patch is test-only) identical production code; tighter test helper Lowest — strictly safer test 1 (winner)
try-fix-1 Symbol-name churn only Low (likely equivalent) 3
try-fix-2 Refactor: helper extraction Low (pure refactor) 4
try-fix-3 Adds cached _triggerThreshold Medium — stale cache for bound Threshold 5
try-fix-4 Drops PR's Math.Min(Threshold, openDistance) cap Medium — regresses the trigger-cap feature commenters asked for 6

Why pr-plus-reviewer wins

  1. Gate-verified production code. It uses 100% of the PR's source-code changes, which are the
    only changes that have empirically passed the gate.
  2. Closes a real false-pass hole in the new test. Copilot's inline review correctly flagged that
    WaitForXPosition returns the last observed X on timeout, so a swipe that fails to register can
    make the equality assertion pass with both sides equal to 0. The sandbox patch makes the helper
    Assert.Fail on timeout — strictly safer.
  3. Strictly better than pr — every test that passes under pr also passes under
    pr-plus-reviewer, but pr-plus-reviewer would additionally catch a class of silent UI-test
    regressions. There is no scenario where pr-plus-reviewer is worse than pr.
  4. The other reviewer suggestions (extract GetTriggerThreshold helper, add iOS 15% floor, prettier
    cache check) are deferred to follow-up — they are nice-to-have cleanup, not bug fixes.

Why all try-fix-* rank lower

Per the prompt's hard rule: “Candidates that failed regression tests MUST be ranked lower than
candidates that passed them.”
The four try-fix candidates were not built or executed in this
environment (no Android emulator available). Treating "not validated" as "not passed", they all rank
strictly below pr and pr-plus-reviewer. Among themselves:

  • try-fix-1 (rename split) — pure naming churn. No upside.
  • try-fix-2 (helper extraction) — non-functional cleanup; better as a follow-up PR so the bug-fix
    PR stays small and easy to revert if needed.
  • try-fix-3 (cache trigger threshold) — has a plausible regression path (bound Threshold won't
    invalidate the cache). Net negative.
  • try-fix-4 (minimal/conservative) — drops the new Math.Min(Threshold, openDistance) cap,
    which is a desirable secondary behaviour the PR introduces (issue commenters asked for less
    sensitive swipes). Net negative.

Recommendation to the PR author

Merge-ready with one suggested follow-up:

  • Apply the WaitForXPosition timeout-fail-fast fix (Copilot inline finding on
    Issue6016.cs:33). This is a 10-line change to the test helper. It strictly improves the test's
    ability to catch silent failures and does not affect production code. See
    expert-pr-eval/content.md for the exact patch.

Optional follow-ups (separate PR):

  • Extract GetTriggerThreshold() helper in both MauiSwipeView.cs files to dedupe the trigger
    formula across Android ProcessTouchUp + RaiseSwipeEnded and iOS ProcessTouchUp.
  • Consider whether iOS should clamp the trigger to Math.Max(Threshold, 0.15 * openDistance) to
    preserve the existing MinimumOpenSwipeThresholdPercentage floor when users set a very small
    Threshold.

Caveats / honest disclosure

  • The agent ran on a Linux runner without Android emulator infrastructure, so try-fix candidates
    could not be built or test-executed locally. Their analyses are static and based on careful code
    reading; they are not empirically validated. The PR's gate result is the only empirical signal.
  • Snapshot baselines (12 PNGs) regenerated by the PR author were not visually re-verified by this
    agent.

@MauiBot MauiBot added s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues labels May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SwipeView Threshold changes width and offset of the side menu (when visible)

6 participants