Skip to content

feat(android): add photos and camera media strip to block inserter#479

Draft
jkmassel wants to merge 1 commit intojkmassel/block-picker-searchfrom
jkmassel/block-picker-media
Draft

feat(android): add photos and camera media strip to block inserter#479
jkmassel wants to merge 1 commit intojkmassel/block-picker-searchfrom
jkmassel/block-picker-media

Conversation

@jkmassel
Copy link
Copy Markdown
Contributor

Summary

Adds the recent-photos / Photos / Camera strip between the inserter header and category tabs. Stacked on top of #469; rebase onto trunk once that lands. Independent of #478 (search/filter PR) — they touch different parts of SheetContent.

Three runtime states:

  1. Permission rationale card — shown when the host app hasn't been granted READ_MEDIA_IMAGES. The card swaps body copy and primary button label depending on whether we've never asked, were denied once, or were permanently denied. SharedPreferences tracks the first prompt because shouldShowRequestPermissionRationale alone can't distinguish "never asked" from "permanently denied".
  2. Recent photos strip — once granted, queries MediaStore for the 12 most recent images, renders as a 2-row thumbnail grid.
  3. Photos / Camera tiles — Photos launches the system photo picker (permissionless via PickVisualMedia); Camera launches ACTION_IMAGE_CAPTURE against a cache-scoped FileProvider URI. Hand-off of the picked URI to editor insertion is a follow-up.

The library declares its own FileProvider keyed off \${applicationId} so it won't collide with one a host app already provides. Hosts that don't need photo access can tools:node=\"remove\" the manifest permissions.

Test plan

  • First launch: rationale card shows with "Allow" + "Reject"
  • Tap Allow → system prompt appears → grant → strip shows recent photos
  • Reject system prompt → rationale switches to "Try Again" copy
  • Reject system prompt twice (or 'don't ask again') → rationale switches to "Open Settings"
  • Tap Reject in rationale → entire strip hides until permission granted via Settings
  • Tap Photos tile → system photo picker opens
  • Tap Camera tile → camera app opens with cache-scoped output URI
  • Vertical drag on the photo strip area still drags the bottom sheet (nested scroll relay)

@github-actions github-actions Bot added the [Type] Enhancement A suggestion for improvement. label Apr 28, 2026
@jkmassel jkmassel marked this pull request as draft April 28, 2026 19:34
jkmassel added a commit that referenced this pull request Apr 28, 2026
Compose-based bottom sheet that replaces the legacy WebView block picker.
Variation B handoff: drag handle + header, tonal Material 3 palette
(dynamic on API 31+, brand-seeded fallback below), 5-column tile grid
with auto-shrinking labels, scrollable category-tab chips, and a rounded
search field.

Block tiles render plain tonal rounded-rect placeholders for now —
SVG icon rendering lands in #468 (which adds `SvgIconCache` and pipes
`iconForeground` through the JS payload + iOS/Android models). This PR
deliberately stops at the shell so #468 can be reviewed independently.

Tab filter, search filter, photo/camera tiles, and recent-photo strip
ship in #478 / #479 — the chips and search bar are intentionally
non-functional in this PR so the visual shell can be reviewed in
isolation.
@jkmassel jkmassel force-pushed the jkmassel/block-picker-organize branch from 7333438 to 43be5d0 Compare April 28, 2026 19:37
@jkmassel jkmassel force-pushed the jkmassel/block-picker-media branch from 9d824ee to d3a1169 Compare April 28, 2026 19:40
@jkmassel jkmassel force-pushed the jkmassel/block-picker-organize branch from 43be5d0 to bfc85d9 Compare April 28, 2026 19:43
@jkmassel jkmassel changed the base branch from jkmassel/block-picker-organize to jkmassel/block-picker-organize-impl April 28, 2026 19:44
jkmassel added a commit that referenced this pull request Apr 28, 2026
Compose-based bottom sheet that replaces the legacy WebView block picker.
Variation B handoff: drag handle + header, tonal Material 3 palette
(dynamic on API 31+, brand-seeded fallback below), 5-column tile grid
with auto-shrinking labels, scrollable category-tab chips, and a rounded
search field.

Block tiles render plain tonal rounded-rect placeholders for now —
SVG icon rendering lands in #468 (which adds `SvgIconCache` and pipes
`iconForeground` through the JS payload + iOS/Android models). This PR
deliberately stops at the shell so #468 can be reviewed independently.

Tab filter, search filter, photo/camera tiles, and recent-photo strip
ship in #478 / #479 — the chips and search bar are intentionally
non-functional in this PR so the visual shell can be reviewed in
isolation.
@jkmassel jkmassel force-pushed the jkmassel/block-picker-organize-impl branch from 43be5d0 to d2a4a4c Compare April 28, 2026 19:58
@jkmassel jkmassel force-pushed the jkmassel/block-picker-media branch from d3a1169 to c966d1c Compare April 28, 2026 19:58
@jkmassel jkmassel force-pushed the jkmassel/block-picker-organize-impl branch from d2a4a4c to b067ac2 Compare April 28, 2026 20:03
jkmassel added a commit that referenced this pull request Apr 28, 2026
Compose-based bottom sheet that replaces the legacy WebView block picker.
Variation B handoff: drag handle + header, tonal Material 3 palette
(dynamic on API 31+, brand-seeded fallback below), 5-column tile grid
with auto-shrinking labels, scrollable category-tab chips, and a rounded
search field.

Block tiles render plain tonal rounded-rect placeholders for now —
SVG icon rendering lands in #468 (which adds `SvgIconCache` and pipes
`iconForeground` through the JS payload + iOS/Android models). This PR
deliberately stops at the shell so #468 can be reviewed independently.

Tab filter, search filter, photo/camera tiles, and recent-photo strip
ship in #478 / #479 — the chips and search bar are intentionally
non-functional in this PR so the visual shell can be reviewed in
isolation.
@jkmassel jkmassel force-pushed the jkmassel/block-picker-media branch from c966d1c to 4cc843e Compare April 28, 2026 20:09
jkmassel added a commit that referenced this pull request Apr 28, 2026
Compose-based bottom sheet that replaces the legacy WebView block picker.
Variation B handoff: drag handle + header, tonal Material 3 palette
(dynamic on API 31+, brand-seeded fallback below), 5-column tile grid
with auto-shrinking labels, scrollable category-tab chips, and a rounded
search field.

Block tiles render plain tonal rounded-rect placeholders for now —
SVG icon rendering lands in #468 (which adds `SvgIconCache` and pipes
`iconForeground` through the JS payload + iOS/Android models). This PR
deliberately stops at the shell so #468 can be reviewed independently.

Tab filter, search filter, photo/camera tiles, and recent-photo strip
ship in #478 / #479 — the chips and search bar are intentionally
non-functional in this PR so the visual shell can be reviewed in
isolation.
@jkmassel jkmassel force-pushed the jkmassel/block-picker-organize-impl branch from b067ac2 to 180a9b7 Compare April 28, 2026 20:12
@jkmassel jkmassel force-pushed the jkmassel/block-picker-media branch from 4cc843e to 5dbe8f3 Compare April 28, 2026 20:13
jkmassel added a commit that referenced this pull request Apr 29, 2026
Compose-based bottom sheet that replaces the legacy WebView block picker.
Variation B handoff: drag handle + header, tonal Material 3 palette
(dynamic on API 31+, brand-seeded fallback below), 5-column tile grid
with auto-shrinking labels, scrollable category-tab chips, and a rounded
search field.

Block tiles render plain tonal rounded-rect placeholders for now —
SVG icon rendering lands in #468 (which adds `SvgIconCache` and pipes
`iconForeground` through the JS payload + iOS/Android models). This PR
deliberately stops at the shell so #468 can be reviewed independently.

Tab filter, search filter, photo/camera tiles, and recent-photo strip
ship in #478 / #479 — the chips and search bar are intentionally
non-functional in this PR so the visual shell can be reviewed in
isolation.
Base automatically changed from jkmassel/block-picker-organize-impl to jkmassel/android-block-picker April 29, 2026 16:18
jkmassel added a commit that referenced this pull request Apr 29, 2026
Compose-based bottom sheet that replaces the legacy WebView block picker.
Variation B handoff: drag handle + header, tonal Material 3 palette
(dynamic on API 31+, brand-seeded fallback below), 5-column tile grid
with auto-shrinking labels, scrollable category-tab chips, and a rounded
search field.

Block tiles render plain tonal rounded-rect placeholders for now —
SVG icon rendering lands in #468 (which adds `SvgIconCache` and pipes
`iconForeground` through the JS payload + iOS/Android models). This PR
deliberately stops at the shell so #468 can be reviewed independently.

Tab filter, search filter, photo/camera tiles, and recent-photo strip
ship in #478 / #479 — the chips and search bar are intentionally
non-functional in this PR so the visual shell can be reviewed in
isolation.
@jkmassel jkmassel force-pushed the jkmassel/android-block-picker branch from dfaf054 to 4067726 Compare April 29, 2026 17:50
@jkmassel jkmassel force-pushed the jkmassel/block-picker-media branch from 5dbe8f3 to a878277 Compare April 29, 2026 19:32
@jkmassel jkmassel changed the base branch from jkmassel/android-block-picker to jkmassel/block-picker-search April 29, 2026 22:15
@jkmassel jkmassel force-pushed the jkmassel/block-picker-media branch 7 times, most recently from f9ac5cd to 8a32386 Compare April 29, 2026 22:55
@jkmassel jkmassel force-pushed the jkmassel/block-picker-search branch from d8ae56e to 79c5380 Compare April 30, 2026 15:34
@jkmassel jkmassel force-pushed the jkmassel/block-picker-media branch 7 times, most recently from 0b46806 to 7e42816 Compare April 30, 2026 21:14
Adds the recent-photos / Photos / Camera strip between the inserter
header and category tabs. Three states, picked at runtime:

1. **Permission rationale card** — shown when the host app hasn't yet
   been granted READ_MEDIA_IMAGES. The card switches body copy and
   primary-button label based on whether we've never asked, were
   denied once, or were permanently denied. SharedPreferences tracks
   the first prompt because `shouldShowRequestPermissionRationale`
   alone can't distinguish "never asked" from "permanently denied".
2. **Recent photos strip** — once granted, queries MediaStore for the
   12 most recent images and renders them as 2-row thumbnail tiles.
3. **Photos / Camera tiles** — Photos launches the system photo
   picker (permissionless via `PickVisualMedia`); Camera launches
   `ACTION_IMAGE_CAPTURE` against a cache-scoped FileProvider URI.
   Hand-off of the picked URI to editor insertion is a follow-up.

The library declares its own FileProvider keyed off `${applicationId}`
so it won't collide with one a host app already provides. Host apps
that don't need photo access can `tools:node="remove"` the manifest
permissions.
@jkmassel jkmassel force-pushed the jkmassel/block-picker-media branch from 7e42816 to 4a31671 Compare April 30, 2026 21:21
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.

1 participant