Skip to content

[iOS] Fix MediaPicker FullPath for PHPicker results - #35805

Merged
kubaflo merged 2 commits into
inflight/currentfrom
jfversluis/mediapicker-regression
Jul 1, 2026
Merged

[iOS] Fix MediaPicker FullPath for PHPicker results#35805
kubaflo merged 2 commits into
inflight/currentfrom
jfversluis/mediapicker-regression

Conversation

@jfversluis

Copy link
Copy Markdown
Member

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

Fixes #32832

MediaPicker on iOS 14+ uses PHPickerViewController. The PHPicker-backed FileResult was returning a synthetic filename for FullPath instead of a real filesystem path, which regressed direct file access patterns such as File.Copy(result.FullPath, ...). Video picking also lost the old compatible representation behavior.

Description of Change

  • Materializes PHPicker results into a MAUI-owned temporary folder before completing pick operations so FileResult.FullPath points to a readable file.
  • Requests compatible asset representation for videos only.
  • Keeps image rotation/resizing/compression on image files only, and ensures processed image results also expose real temp-backed FullPath values.
  • Adds cleanup for stale MediaPicker temporary files and explicit cleanup on dispose/error paths.
  • Removes the shared static picker reference to avoid overlapping picker lifecycle races.

Testing

  • dotnet format src/Essentials/src/Essentials.csproj --no-restore --include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity minimal
  • dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0 --no-restore /p:BuildIpa=false /p:EnableSourceLink=false /p:UseSharedCompilation=false
  • dotnet build src/Essentials/src/Essentials.csproj -f net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false /p:UseSharedCompilation=false

Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie @DennisWelu if you are able, could you please try the artifacts from this PR and confirm whether they restore your iOS MediaPicker scenarios for photos/videos and FullPath access?

Materialize PHPicker results into managed temporary files before returning so FileResult.FullPath points to a readable path on iOS.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🚀 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 -- 35805

Or

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

@github-actions github-actions Bot added area-essentials Essentials: Device, Display, Connectivity, Secure Storage, Sensors, App Info platform/ios platform/macos macOS / Mac Catalyst labels Jun 8, 2026
@kubaflo

kubaflo commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer

@MauiBot MauiBot added s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Jun 8, 2026
MauiBot

This comment was marked as outdated.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please check the ai's suggestions?

Clean up failed PHPicker loads, remove dead multi-select capture path, and keep processed file writes off the captured context.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kubaflo

kubaflo commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/regression-check -p ios

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Reviewing test failures on this PR... Review PR Test Failures

@jfversluis

Copy link
Copy Markdown
Member Author

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie @DennisWelu The PR has been updated and is ready for testing. Could you please try the artifacts from this PR and let us know whether it fixes the iOS MediaPicker FullPath regression for photos/videos in your apps?

I manually verified the iOS video path scenario with a local test app using this branch: FullPath is now an absolute temp path under maui-mediapicker, File.Exists(FullPath) is true, and OpenReadAsync() reads the same file length. For videos, the picker requests the compatible asset representation to restore the previous iOS transcoding/compatible-output behavior where the system provides it.

Artifact install instructions are in the PR description and the dogfood comment above. Thanks!

@kubaflo

kubaflo commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer -p ios

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jun 13, 2026
MauiBot

This comment was marked as outdated.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jun 13, 2026

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please check the latest suggestions?

@craftylogic

Copy link
Copy Markdown

Hi @jfversluis,

Apologies - I can't seem to run the script as I'm getting an error:

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

╔═══════════════════════════════════════════════════════════╗
║                                                           ║
║        .NET MAUI PR Build Applicator                     ║
║                                                           ║
╚═══════════════════════════════════════════════════════════╝



▶️  Finding MAUI project
✅ Found project: XYZ.csproj

▶️  Fetching PR information
ℹ️  Fetching PR #35805 information from GitHub...
ℹ️  PR #35805: [iOS] Fix MediaPicker FullPath for PHPicker results
ℹ️  State: open

▶️  Detecting target framework
ℹ️  Current target framework: .NET 10.0

▶️  Finding build artifacts
ℹ️  Looking for build artifacts for commit 8048cfd...
⚠️  Build completed with status: failure

❌ Build was not successful. Aborting.

Should I try again later or try something else? It looks like there are build failures.

Thanks.

@jfversluis

Copy link
Copy Markdown
Member Author

@craftylogic there are manual steps here as well: https://github.com/dotnet/maui/wiki/Testing-PR-Builds trying to figure out the script

@craftylogic

Copy link
Copy Markdown

@jfversluis Thanks for the manual steps - I used the instructions to find the build artefacts at this address:

Build Artefacts

Once I worked out how to get the nupkg files into my nuget.config LocalPackages I was able to force the downloaded Maui.Essentials library to be included. Based on this warning I assume my CSPROJ file changes allowed the local NUPKG to load:

Detected package version outside of dependency constraint: CommunityToolkit.Maui.Core 10.0.0 requires Microsoft.Maui.Essentials (>= 9.0.21 && < 10.0.0) but version Microsoft.Maui.Essentials 10.0.80-ci.pr35805.26312.37 was resolved.

With this release I can now confirm that my 'FullPath' issue is resolved as can be seen in this screen capture:

image

Thank you for all your efforts!

jfversluis added a commit that referenced this pull request Jun 24, 2026
<!-- 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

Updates `eng/scripts/get-maui-pr.sh` and `eng/scripts/get-maui-pr.ps1`
so users can still apply PR package artifacts when the aggregate
`maui-pr` build is red because of unrelated CI legs, as long as the
package-producing artifacts exist for the current PR commit.

### Changes

- Treat a red aggregate `maui-pr` build as a warning instead of an
immediate abort.
- Keep `PackageArtifacts` as the hard gate before downloading/applying
packages.
- Filter AzDO fallback builds to the current PR head/merge context using
`triggerInfo.pr.sourceSha`, `sourceVersion`, and the PR merge SHA.
- Warn when `Pack macOS` or `Pack Windows` timeline records do not
report success.
- Update troubleshooting text to refer to completed `maui-pr` builds
with `PackageArtifacts` rather than green checks.

### Validation

- `bash -n eng/scripts/get-maui-pr.sh`
- PowerShell parser validation for `eng/scripts/get-maui-pr.ps1`
- `git diff --check`
- Local throwaway MAUI projects under
`/Volumes/NieuwVolume/maui-pr-artifact-verification-20260616101523`:
- PR `#35805`: red aggregate build `1461390`, `PackageArtifacts`
present, pack jobs succeeded; Bash and PowerShell scripts applied
package `10.0.80-ci.pr35805.26312.37`; `dotnet restore` succeeded.
- PR `#35923`: green aggregate build path applied package
`10.0.80-ci.pr35923.26315.57`; `dotnet restore` succeeded.
- PR `#35626`: missing `PackageArtifacts` failed before mutating the
project.
  - PR `#999999`: nonexistent PR failed cleanly during PR lookup.
- Wrong-SHA harness for PR `#35805`: refused to use older completed
builds when none matched the requested head/merge commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jul 1, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Expert Review — 1 findings

See inline comments for details.

// Create a temp file for the rotated image
var tempFileName = $"{Guid.NewGuid()}{Path.GetExtension(result.FileName)}";
var tempFilePath = Path.Combine(Path.GetTempPath(), tempFileName);
var tempFilePath = PHPickerFileResult.CreateTemporaryFilePath(Path.GetExtension(result.FileName));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🔍 AI-Generated Review (multi-model)

[moderate] Regression PreventiontempFilePath is created inside the rotation try, so the catch cannot delete it if File.Create(tempFilePath) succeeds but rotatedStream.CopyToAsync(...) throws (for example on a low-storage device). That leaves a 0-byte/partial file in the maui-mediapicker temp directory until the 24-hour stale sweep; the same pattern appears in RotateImageFile at line 517. Hoist the temp path before the try and call PHPickerFileResult.TryDeleteTemporaryFile(tempFilePath) from the catch before falling back to the original result.

@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-win AI found a better alternative fix than the PR labels Jul 1, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AI Review Summary

@jfversluis — new AI review results are available based on this last commit: 8048cfd. To request a fresh review after new comments or commits, comment /review rerun.

Gate Inconclusive Confidence Low Platform iOS


🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix

Gate Result: ⚠️ INCONCLUSIVE

Platform: IOS

⚠️ verify-tests-fail.ps1 exited before writing a verification report. Diagnostics below.

Exit code: 3

Likely cause:

  • Test detection failed — no runnable tests were found in the PR diff.
Gate output log (last 60 lines)
📁 Output directory: CustomAgentLogsTmp/PRState/35805/PRAgent/gate/verify-tests-fail
🔍 Detecting base branch and merge point...
No PR detected, scanning remote branches for closest base...
✅ Base branch: main (via closest-merge-base)
✅ Merge base commit: fa1d0d2d
   (1 commits ahead of main)
╔═══════════════════════════════════════════════════════════╗
║         FULL VERIFICATION MODE                            ║
╠═══════════════════════════════════════════════════════════╣
║  Fix files detected - will verify:                        ║
║  1. Tests FAIL without fix                                ║
║  2. Tests PASS with fix                                   ║
╚═══════════════════════════════════════════════════════════╝
✅ Fix files (1):
   - src/Essentials/src/MediaPicker/MediaPicker.ios.cs
🔍 Auto-detecting test filter from changed test files...
⚠️ No tests detected in this PR.
   Searched for: UI tests, unit tests, XAML tests, device tests
   Consider adding tests via write-tests-agent.

📱 UI Tests — Essentials

Detected UI test categories: Essentials

⏭️ Deep UI tests — 0 passed, 0 failed across 1 category on platform-pool agent (replaces in-process counts above). 1 category reported 0 tests.

🧪 UI Test Execution Results (deep, platform pool)

Category Tests Snapshot diffs
Essentials 0 tests
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)

📋 Pre-Flight — Context & Validation

Issue: #32832 - MediaPicker.PickVideosAsync returns only file names as file path and doesn't compress the videos anymore under iOS
PR: #35805 - [iOS] Fix MediaPicker FullPath for PHPicker results
Platforms Affected: iOS, MacCatalyst
Files Changed: 1 implementation, 0 test

Key Findings

  • The regression starts in .NET 10 preview 4+ for iOS PHPicker scenarios: PickVideoAsync, PickVideosAsync, and commenters report photo variants returning only a filename/synthetic path instead of a readable filesystem path.
  • The PR's current fix materializes PHPicker results into MAUI-owned temp files, requests compatible representation for videos, skips image processing for non-images, adds temp cleanup/disposal, and removes the shared static picker reference.
  • User artifact testing by craftylogic reported the FullPath issue resolved with this PR's package.
  • GitHub CLI is unauthenticated in this environment, so pre-flight used local branch state and public GitHub API reads; required-check state remains undetermined here. The provided gate result is inconclusive and was not re-run.

Code Review Summary

Verdict: NEEDS_CHANGES
Confidence: low
Errors: 1 | Warnings: 1 | Suggestions: 1

Key code review findings:

  • ✗ Missing regression coverage for the fixed PHPicker FullPath contract; no test files were added.
  • ⚠ Temp files can survive failed rotation writes in src/Essentials/src/MediaPicker/MediaPicker.ios.cs:310-329 and :517-531 until stale cleanup.
  • ℹ Comment at src/Essentials/src/MediaPicker/MediaPicker.ios.cs:393 is stale/incorrect.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #35805 Materialize PHPicker results into MAUI-owned temp files with cleanup/disposal/lifecycle protections; request compatible video representation; image-process images only. ⚠️ INCONCLUSIVE (Gate) src/Essentials/src/MediaPicker/MediaPicker.ios.cs Original PR; code review found implementation direction sound but missing regression coverage.

🔬 Code Review — Deep Analysis

Code Review — PR #35805

Independent Assessment

What this changes: iOS MediaPicker now materializes PHPicker results into MAUI-owned temp files, applies compatible video representation, and eagerly processes rotation/compression so FullPath points to readable files.
Inferred motivation: Fix PHPicker-backed FileResult.FullPath being a synthetic/non-readable path and reduce picker lifecycle races.

Reconciliation with PR Narrative

Author claims: Fixes iOS PHPicker FullPath, video compatibility, image-only processing, temp cleanup, static picker removal.
Agreement/disagreement: Matches the implementation. The main gap is regression coverage for the fixed FullPath contract.

Prior Review Reconciliation

Prior ❌ Error Finding Source Status Evidence
Missing regression coverage for fixed FullPath contract MauiBot reviews on commit 8048cfd ❌ Unresolved Current diff changes only src/Essentials/src/MediaPicker/MediaPicker.ios.cs; no test files added.

Blast Radius Assessment

  • Runs for all instances: No — only iOS/MacCatalyst MediaPicker calls.
  • Startup impact: No.
  • Static/shared state: Reduced; removes static PickerRef. New temp directory cleanup is shared but scoped to maui-mediapicker.

CI Status

  • Required-check result: gh pr checks --required unavailable (gh unauthenticated). Public check-runs show maui-pr / Build Analysis failing.
  • Classification: likely PR-unrelated; failed Helix unit test is Windows MauiAppBuild_BeginInvoke_DispatchesToDispatcher, while PR changes iOS MediaPicker only.
  • Action taken: invoked CI investigation path with public APIs; confidence capped low.

Findings

❌ Error — Missing regression coverage for fixed FullPath contract

The PR fixes a user-visible contract: PHPicker FileResult.FullPath should be a real readable file path. No regression test or device/UI coverage was added, and prior MauiBot ❌ findings for this remain unresolved. Per workflow rules, unresolved prior ❌ findings require NEEDS_CHANGES.

⚠️ Warning — Temp files can survive failed rotation writes

src/Essentials/src/MediaPicker/MediaPicker.ios.cs:310-329 and :517-531 create temp paths inside try blocks but do not delete the temp path if File.Create succeeds and CopyToAsync later throws. These are eventually swept by stale cleanup, but low-storage/write-failure paths can leak files for up to 24 hours.

💡 Suggestion — Incorrect comment

src/Essentials/src/MediaPicker/MediaPicker.ios.cs:393 says the method is only for iOS < 14, but the guard returns null for < 14 and proceeds on iOS 14+.

Failure-Mode Probing

  • Swipe dismissal during async processing: completion paths null the presentation handler before explicit dismissal; swipe-dismiss still uses TrySetResult, so double completion is benign.
  • Failed provider load: current code disposes the in-flight PHPickerFileResult and accumulated results.
  • Non-image video processing: guarded by IsImageFile, so resizing/rotation avoids videos.

Verdict: NEEDS_CHANGES

Confidence: low
Summary: Implementation direction looks sound and CI failure appears unrelated, but the unresolved prior ❌ test-coverage finding blocks LGTM under the skill rules. Add focused regression coverage or obtain explicit maintainer waiver.


🛠️ Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix-1 Eagerly materialize PHPickerFileResult via LoadFileRepresentation before picker completion. ✅ Build passed / ❌ self-review failed 1 file Minimal and likely fixes FullPath, but lacks single-flight concurrency, cancellation/disposal, and owned cleanup.
2 try-fix-2 Prefer LoadInPlaceFileRepresentation provider URL, fallback to copy. ✅ Build passed / ❌ self-review failed 1 file Avoids copies when possible, but in-place provider URLs are not durable enough for the FullPath contract after picker completion.
3 try-fix-3 Persist the existing FileResult.OpenReadAsync stream into a temp file. ✅ Build passed / ❌ self-review failed 1 file Restores a path through the existing abstraction, but keeps LoadDataRepresentation/NSData memory risk for large videos.
PR PR #35805 Copy LoadFileRepresentation output into MAUI-owned temp files with cleanup/disposal/lifecycle protections; request compatible video representation. ⚠️ Gate inconclusive 1 file Best implementation among explored options; still missing regression coverage per code review.

Cross-Pollination

Model/Reviewer Round New Ideas? Details
maui-expert-reviewer 2 No NO NEW IDEAS: PhotoKit/assetIdentifier + PHAssetResourceManager/export is the remaining distinct avenue, but it is not likely better because it can require Photos-library authorization, fail for nil identifiers/iCloud/limited-library cases, complicate compatible-video export, and reintroduce representation/lifecycle variability.

Exhausted: Yes
Selected Fix: PR #35805 — The PR's MAUI-owned temp-file approach is more robust than all alternatives generated here because it avoids LoadDataRepresentation memory pressure, avoids non-durable in-place URLs, and owns cleanup/disposal. It is not fully verified because the gate was inconclusive and no regression test exists.


🏁 Report — Final Recommendation

Comparative Report — PR #35805

Candidate ranking

Rank Candidate Regression/build result Assessment
1 pr-plus-reviewer ⚠️ Gate inconclusive; not a failing fix Best candidate. It keeps the PR's durable MAUI-owned temp-file implementation and applies the expert cleanup feedback for partially-created rotated temp files.
2 pr ⚠️ Gate inconclusive; not a failing fix Strongest submitted implementation. It restores FullPath using LoadFileRepresentation, avoids in-place URL lifetime issues, avoids LoadDataRepresentation video memory pressure, adds scoped temp ownership, and removes shared picker state.
3 try-fix-1 ✅ iOS Essentials build passed; ❌ self-review failed Likely fixes the visible FullPath symptom, but lacks the PR's single-flight load protection, cancellation/disposal handling, and scoped cleanup.
4 try-fix-3 ✅ iOS Essentials build passed; ❌ self-review failed Restores a path through OpenReadAsync, but keeps the LoadDataRepresentation/NSData path that can be unsafe for large videos.
5 try-fix-2 ✅ iOS Essentials build passed; ❌ self-review failed Provider in-place URLs are not durable enough for MAUI's FileResult.FullPath contract after picker completion, so this is the riskiest correctness model.

No candidate had a confirmed failing regression test. The provided PR gate was inconclusive and Step 5a candidates only had local build/self-review evidence, so ranking is based on code correctness, lifecycle safety, and the known failure modes from expert review.

Winning candidate

Winner: pr-plus-reviewer

pr-plus-reviewer wins because it preserves the PR's MAUI-owned temp-file architecture while addressing the only actionable cleanup gap found during expert review. It is superior to all try-fix candidates because it avoids non-durable provider URLs, avoids loading large videos into memory, and includes lifecycle/concurrency protections around provider file materialization.


🧭 Next Steps — review latest findings

No alternative fix was selected for this run. Review the session findings and CI results before merging.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jul 1, 2026
@kubaflo

kubaflo commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

@craftylogic thank you soo much for testing it <3

@kubaflo
kubaflo changed the base branch from main to inflight/current July 1, 2026 13:59
@kubaflo
kubaflo merged commit 2642654 into inflight/current Jul 1, 2026
29 of 32 checks passed
@kubaflo
kubaflo deleted the jfversluis/mediapicker-regression branch July 1, 2026 13:59
@github-actions github-actions Bot added this to the .NET 10 SR9 milestone Jul 1, 2026
kubaflo pushed a commit that referenced this pull request Jul 3, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kubaflo kubaflo mentioned this pull request Jul 6, 2026
kubaflo pushed a commit that referenced this pull request Jul 6, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PureWeen pushed a commit that referenced this pull request Jul 7, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PureWeen pushed a commit that referenced this pull request Jul 7, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jul 10, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jul 15, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jul 22, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jul 28, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo pushed a commit that referenced this pull request Jul 29, 2026
<!-- 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

Fixes #32832

`MediaPicker` on iOS 14+ uses `PHPickerViewController`. The
PHPicker-backed `FileResult` was returning a synthetic filename for
`FullPath` instead of a real filesystem path, which regressed direct
file access patterns such as `File.Copy(result.FullPath, ...)`. Video
picking also lost the old compatible representation behavior.

### Description of Change

- Materializes PHPicker results into a MAUI-owned temporary folder
before completing pick operations so `FileResult.FullPath` points to a
readable file.
- Requests compatible asset representation for videos only.
- Keeps image rotation/resizing/compression on image files only, and
ensures processed image results also expose real temp-backed `FullPath`
values.
- Adds cleanup for stale MediaPicker temporary files and explicit
cleanup on dispose/error paths.
- Removes the shared static picker reference to avoid overlapping picker
lifecycle races.

### Testing

- `dotnet format src/Essentials/src/Essentials.csproj --no-restore
--include src/Essentials/src/MediaPicker/MediaPicker.ios.cs --verbosity
minimal`
- `dotnet build src/Essentials/src/Essentials.csproj -f net10.0-ios26.0
--no-restore /p:BuildIpa=false /p:EnableSourceLink=false
/p:UseSharedCompilation=false`
- `dotnet build src/Essentials/src/Essentials.csproj -f
net10.0-maccatalyst26.0 --no-restore /p:EnableSourceLink=false
/p:UseSharedCompilation=false`

### Artifact Testing Request

@stefanottauma @BohdanRomaniuk @craftylogic @marcojak @msoftie
@DennisWelu if you are able, could you please try the artifacts from
this PR and confirm whether they restore your iOS MediaPicker scenarios
for photos/videos and `FullPath` access?

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-essentials Essentials: Device, Display, Connectivity, Secure Storage, Sensors, App Info platform/ios platform/macos macOS / Mac Catalyst 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)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MediaPicker.PickVideosAsync returns only file names as file path and doesn't compress the videos anymore under iOS

4 participants