Skip to content

fix(ios): surface block inserter media failures to the user - #598

Open
dcalhoun wants to merge 1 commit into
trunkfrom
fix/block-inserter-media-error-alert
Open

fix(ios): surface block inserter media failures to the user#598
dcalhoun wants to merge 1 commit into
trunkfrom
fix/block-inserter-media-error-alert

Conversation

@dcalhoun

@dcalhoun dcalhoun commented Aug 21, 2026

Copy link
Copy Markdown
Member

What?

Media import failures in the native block inserter showed the user nothing at all. BlockInserterViewModel.error was assigned but never read by any view, so a failed photo import or camera capture left the inserter sheet open with no feedback.

Why?

The lack of user feedback during causes confusion.

How?

Bind error to an .alert(item:) in BlockInserterViewMediaError is already Identifiable.

Replace the system-derived messages with a small set of localized strings. Previously the picker path surfaced error.localizedDescription, which for the common URLError.unknown case is generic text that tells a user nothing actionable, and the camera path threw an unlocalized "Failed to convert image to JPEG" literal. Three new EditorLocalization cases: one shared alert title, one message per failure family, plus ok. Hosts that do not translate them fall back to the editor's own strings and get a one-time log, per the existing design.

Testing Instructions

Neither failure is easy to trigger organically — the picker path realistically needs an offloaded iCloud photo with no network, and the camera path needs a device. Apply the patch below to force both.

Reproduction patch — forces both failures

Both failures fire from independent entry points, so this triggers each one without toggling anything: the photo button demonstrates one message, the camera button the other.

diff --git a/ios/Sources/GutenbergKit/Sources/Views/BlockInserter/BlockInserterView.swift b/ios/Sources/GutenbergKit/Sources/Views/BlockInserter/BlockInserterView.swift
--- a/ios/Sources/GutenbergKit/Sources/Views/BlockInserter/BlockInserterView.swift
+++ b/ios/Sources/GutenbergKit/Sources/Views/BlockInserter/BlockInserterView.swift
@@ -179,7 +179,10 @@ struct BlockInserterView: View {
             }
 
             Button {
-                isShowingCamera = true
+                // TEMPORARY: route straight to `processCameraMedia` so the
+                // captured-media alert is reachable in the Simulator, which
+                // has no camera.
+                insertCameraMedia(.photo(UIImage()))
             } label: {
                 Image(systemName: "camera")
             }
diff --git a/ios/Sources/GutenbergKit/Sources/Views/BlockInserter/BlockInserterViewModel.swift b/ios/Sources/GutenbergKit/Sources/Views/BlockInserter/BlockInserterViewModel.swift
--- a/ios/Sources/GutenbergKit/Sources/Views/BlockInserter/BlockInserterViewModel.swift
+++ b/ios/Sources/GutenbergKit/Sources/Views/BlockInserter/BlockInserterViewModel.swift
@@ -77,6 +77,7 @@ class BlockInserterViewModel: ObservableObject {
             var anyError: Error?
 
             do {
+                throw URLError(.unknown) // TEMPORARY: force picker failure.
                 for item in items {
                     let item = try await self.fileManager.import(item)
                     results.append(item)
@@ -108,6 +109,9 @@ class BlockInserterViewModel: ObservableObject {
             do {
                 let mediaInfo: MediaInfo
 
+                // TEMPORARY: force camera failure.
+                throw MediaError(message: EditorLocalization[.failedToProcessCapturedMedia])
+
                 switch media {
                 case .photo(let image):
                     guard let imageData = image.jpegData(compressionQuality: 0.8) else {

This produces two code after 'throw' will never be executed warnings. Expected — wrapping each throw in if true { } silences them if you prefer a clean build.

With the patch applied, in the Demo app:

  1. Open a post and tap + to open the block inserter.
  2. Tap the photo toolbar button and select any image. Expected: an alert titled "Failed to insert media" with "The selected media could not be loaded. It may not be fully downloaded to this device."
  3. Dismiss, then select an image via the inline picker under "Most used" and tap the +N confirm button. Expected: the same alert.
  4. Tap the camera toolbar button. Expected: an alert titled "Failed to insert media" with "The captured media could not be processed."
  5. Confirm the alert renders correctly over the still-presented inserter sheet, and that dismissing it leaves the inserter usable.

Then revert the patch and confirm the regression path:

  1. Insert a photo normally. Expected: it inserts as before, with no alert.

Accessibility Testing Instructions

With VoiceOver enabled, follow the steps above. On failure, VoiceOver should announce the alert title and message, and focus should move into the alert. Confirm the OK button is reachable and dismisses it, returning focus to the inserter.

Screenshots or screencast

Media strip Camera
media-strip camera

`BlockInserterViewModel.error` was assigned on media import failure but
never read, so a failed photo import or camera capture showed nothing at
all — the inserter sheet stayed open with no feedback.

Bind the property to an alert, and replace the system-derived messages
with a small set of localized strings. `URLError.unknown`'s description
tells a user nothing actionable, and it is the likeliest failure (an
iCloud photo not downloaded to the device). The camera path's message
was also an unlocalized string literal.

Also log the underlying error on both paths so the detail dropped from
the user-facing message stays diagnosable, and only surface the picker
alert when an error actually occurred, so an empty selection does not
raise a spurious one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SrZVz6gAuLjo6Dj8hTNeJv
@github-actions github-actions Bot added the [Type] Bug An existing feature does not function as intended label Aug 21, 2026
@wpmobilebot

Copy link
Copy Markdown

XCFramework Build

This PR's XCFramework is available for testing. Add the following to your Package.swift:

.package(url: "https://github.com/wordpress-mobile/GutenbergKit", branch: "pr-build/598")

Built from cc36aa8

@dcalhoun
dcalhoun marked this pull request as ready for review August 21, 2026 23:11
@dcalhoun
dcalhoun requested a review from crazytonyli August 21, 2026 23:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants