Skip to content

feat(android): add Photos and Camera tiles to block inserter#509

Merged
jkmassel merged 3 commits into
trunkfrom
jkmassel/block-picker-photos-camera
May 14, 2026
Merged

feat(android): add Photos and Camera tiles to block inserter#509
jkmassel merged 3 commits into
trunkfrom
jkmassel/block-picker-photos-camera

Conversation

@jkmassel
Copy link
Copy Markdown
Contributor

@jkmassel jkmassel commented May 13, 2026

Summary

Adds a Photos / Camera quick-launch row between the inserter's header and category tabs. First slice of a four-part split of #479; covers just the permissionless tiles.

  • Photos tile uses ActivityResultContracts.PickVisualMedia — the system photo picker, no manifest permission required.
  • Camera tile uses ACTION_IMAGE_CAPTURE against a cache-scoped FileProvider URI. The library does not declare or request CAMERA — but per the MediaStore.ACTION_IMAGE_CAPTURE docs, if a host app does declare CAMERA in its merged manifest, Android requires the host to hold it at runtime before the intent dispatches. That's a host-app concern, not a library one — flagging it here so the follow-up that wires up the hand-off doesn't get surprised.

The library declares its own FileProvider keyed off ${applicationId}.gutenberg.fileprovider so it can't collide with one a host app already declares.

No uses-permission lines are added in this PR. The recent-photos thumbnail strip that needs READ_MEDIA_IMAGES lands in the follow-up.

Inserter, light mode Inserter, dark mode
Light mode Dark mode

Design notes

  • The icon and label inside each tile are deliberately tight — no Spacer between them. The block tiles below use an 8dp gap; the media tiles are intentionally punchier to read as quick actions, not as members of the block grid.

What does not land here (follow-ups)

  • Recent-photos thumbnail strip, photo-permission rationale, and the READ_MEDIA_IMAGES / READ_EXTERNAL_STORAGE declarations — next PR in the stack.
  • Android 14 READ_MEDIA_VISUAL_USER_SELECTED partial-access support and the "Manage" tile — PR after that.
  • Touch-target accessibility fix for the existing category chips — independent PR.

Result-callback inertness

Both launcher result callbacks are intentionally empty:

ActivityResultContracts.PickVisualMedia()
) { /* picked uri — hand-off to editor insertion is a follow-up */ }

The picked URI / camera capture needs to round-trip through WebViewAssetLoader so the JS editor can fetch() it — that hand-off is a follow-up. Until then, this whole sheet is gated behind the demo's "Enable Native Inserter" toggle, so users outside that opt-in don't see the no-op buttons.

A TODO on createCameraOutputUri flags that each Camera tap creates an orphan file in the cache today; cleanup lands when the hand-off does.

Test plan

  • Open the inserter in the demo app. Photos and Camera tiles render above the category tabs.
  • Tap Photos → system photo picker opens. Pick or cancel → sheet returns to the inserter intact.
  • Tap Camera → camera app opens with a cache-scoped output URI. Capture or cancel → sheet returns to the inserter intact.
  • Camera tile is hidden on devices that don't report FEATURE_CAMERA_ANY (tablet/emulator without a camera).
  • ./gradlew :Gutenberg:detekt :Gutenberg:assembleDebug :Gutenberg:testDebugUnitTest passes.

@wpmobilebot
Copy link
Copy Markdown

wpmobilebot commented May 13, 2026

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/509")

Built from 7e94992

@jkmassel jkmassel force-pushed the jkmassel/block-picker-photos-camera branch 5 times, most recently from 50da710 to 6353b11 Compare May 13, 2026 18:35
Adds a Photos / Camera quick-launch row between the inserter's header
and category tabs:

- Photos tile uses the permissionless system photo picker
  (`ActivityResultContracts.PickVisualMedia`) — no manifest permission
  required.
- Camera tile uses `ACTION_IMAGE_CAPTURE` against a cache-scoped
  FileProvider URI; no `CAMERA` permission required since we delegate
  to the system camera app.

The library declares its own FileProvider keyed off
`${applicationId}.gutenberg.fileprovider` so it can't collide with one
a host app already declares. No `uses-permission` lines added at this
stage — the recent-photos thumbnail strip that needs
`READ_MEDIA_IMAGES` lands in a follow-up.

The picker / camera result callbacks are intentionally inert until the
WebViewAssetLoader-based URI hand-off lands; the sheet is gated behind
the demo's "Enable Native Inserter" toggle in the meantime.
@jkmassel jkmassel force-pushed the jkmassel/block-picker-photos-camera branch from 6353b11 to 0943b8a Compare May 13, 2026 18:40
@jkmassel jkmassel requested a review from adalpari May 13, 2026 18:42
…aUri comment

Wrap PickVisualMediaRequest in `remember { ... }` so the request isn't
rebuilt on each recomposition, and expand the pendingCameraUri comment
to make clear it's set for the follow-up TakePicture callback (the inert
callback today doesn't read it).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@adalpari adalpari left a comment

Choose a reason for hiding this comment

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

Just made a small change related to recomposition.
But overall, the PR looks good to me! 🚢 it!!

The earlier remember wrap pushed MediaStrip to 60 lines, tripping
Detekt's LongMethod (threshold 60). Collapse to a single line — fits
under MaxLineLength (140).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jkmassel jkmassel merged commit c81904f into trunk May 14, 2026
22 checks passed
@jkmassel jkmassel deleted the jkmassel/block-picker-photos-camera branch May 14, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants