fix(ios): import picker media per-item so one failure doesn't drop the rest - #623
Draft
jkmassel wants to merge 2 commits into
Draft
fix(ios): import picker media per-item so one failure doesn't drop the rest#623jkmassel wants to merge 2 commits into
jkmassel wants to merge 2 commits into
Conversation
…e rest The native block inserter imported a multi-photo selection in a single do/catch loop, so the first item that failed to import aborted the whole selection — every item after it was skipped, and no error was shown unless nothing imported at all. A failure alongside a success was dropped silently. Import each item independently: insert the ones that succeed and surface an error for any that fail, including a partial failure (which now names how many items were skipped). A total failure keeps the existing message and leaves the inserter open to retry. Android's native block picker routes picked media through inert callbacks today, so there's no equivalent import loop to change.
XCFramework BuildThis PR's XCFramework is available for testing. Add the following to your .package(url: "https://github.com/wordpress-mobile/GutenbergKit", branch: "pr-build/623")Built from 1c1df6e |
jkmassel
marked this pull request as draft
September 5, 2026 01:28
…rotocol processSelectedPhotosPickerItems' import loop couldn't be tested because PhotosPickerItem can't be constructed in a test — the earlier tests only exercised the error-message helper in isolation. Add an ImportableMediaItem protocol that PhotosPickerItem conforms to via an empty extension. MediaFileManager.import and processSelectedPhotosPickerItems now take `some ImportableMediaItem`, and the view model's MediaFileManager is injectable. Tests drive the real loop with a mock item and a temp-directory file manager, covering partial failure (successes kept, error surfaced), total failure, and full success. No production behavior change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a bug where importing a multi-photo selection in the native block inserter dropped every item after the first one that failed to import — and, when a failure landed alongside a success, surfaced no error at all.
Summary
do/catchloop, so the first item that failed to import aborted the whole selection — every item after it was skipped.results.isEmpty, so a failure alongside a success was dropped silently.Root Cause
BlockInserterViewModel.processSelectedPhotosPickerItemswrapped the entireforloop in onedo/catch. A throw fromMediaFileManager.import— e.g. a photo not fully downloaded from iCloud, or one too large to materialize into memory — jumped straight to thecatch, so items after the failure were never attempted. Theif results.isEmptygate then meant a partial failure showed nothing.Fix
BlockInserterViewModel.swift: import each item in its owndo/catch, counting failures. After the loop, resolve the alert through a new testableimportError(failureCount:successCount:)— the existing "nothing could be loaded" copy when everything failed, or a new count-aware message on a partial failure.BlockInserterView.swift: on any failure, insert whatever succeeded and keep the inserter open so its alert is visible. Acknowledging the alert closes the inserter only on a partial success; a total failure leaves it open to retry — unchanged from today.EditorLocalization.swift: addsomeSelectedMediaFailedToLoad(Int)with singular/plural defaults.Testability
PhotosPickerItemcan't be constructed in a test, so the import loop had no direct coverage. A newImportableMediaItemprotocol captures the slice ofPhotosPickerItemthatMediaFileManager.importuses (supportedContentTypes,loadTransferable);PhotosPickerItemconforms via an empty extension, andimport/processSelectedPhotosPickerItemsnow takesome ImportableMediaItem. The view model'sMediaFileManageris injectable, so tests drive the real loop with a mock item and a temp-directory file manager. No production behavior change.Test Plan
make lint-swiftclean on the changed files.BlockInserterViewModelTestsdrives the real import loop — partial failure (successes kept, error surfaced), total failure, and full success — plusEditorLocalizationTests.defaultsPluralizeSkippedMediaCounts.Notes
ItemProviderMediaExporterupload hang: that's the host's Media Library picker, reached viaopenMediaLibrary→ the host delegate — a different code path from this inserter import.🤖 Generated with Claude Code