Add frontend support for up to 10 images

Frontend plumbing for the Photos v2 increase from 4 to 10 images.

- Bump MAX_IMAGES from 4 to 10 in the composer; downstream consumers read the
  constant dynamically, so selection limits and copy follow automatically.
- In-feed display rule per the Photos v2 spec: 1 image renders the single
  view, 2-4 render the existing grid, >4 render the carousel. This is gated
  behind the existing PostGalleryEmbedEnable flag, which now acts as a
  carousel kill-switch.
- Fix the reply-to thumbnail to show a 2x2 preview of the first 4 images for
  any post with >=4 images (previously it rendered blank for >4).

Note: actually publishing >4 images additionally requires the
app.bsky.embed.images lexicon maxLength to be raised in @atproto/api (PR in
flight). Until that lands, posts with >4 images are rejected by
applyWrites({validate: true}). This change is UI-only and safe behind the flag.

APP-2197
This commit is contained in:
vineyardbovines
2026-06-03 19:29:09 -04:00
parent 153772b760
commit 843b9b540f
4 changed files with 26 additions and 5 deletions
+19 -1
View File
@@ -15,6 +15,14 @@ import {useAnalytics} from '#/analytics'
import {type EmbedType} from '#/types/bsky/post'
import {type CommonProps} from './types'
/**
* Posts with more than this many images render the swipeable carousel
* (Gallery) instead of the static grid (ImageLayoutGrid). Per the Photos v2
* spec: show the grid for up to 4 photos, show the carousel for more than 4.
* The grid only supports up to 4 images, so this is also the grid's max.
*/
const GALLERY_IMAGE_THRESHOLD = 4
export function ImageEmbed({
embed,
...rest
@@ -24,7 +32,17 @@ export function ImageEmbed({
const ax = useAnalytics()
const {openLightbox} = useLightboxControls()
const {images} = embed.view
// PostGalleryEmbedEnable is kept as a kill-switch for the carousel. When the
// flag is ON (the intended state), the grid-vs-carousel choice follows
// GALLERY_IMAGE_THRESHOLD: 2-4 images use the existing grid, >4 use the
// carousel. The 2-4 grid is intentionally preserved (decoupled from the 4->10
// launch) per the Photos v2 spec. When the flag is OFF, the carousel is
// suppressed entirely and we fall back to the pre-carousel behavior: the grid
// renders the first 4 images. NOTE: with the flag OFF, images beyond the first
// 4 are not shown - this is the same limitation the grid always had, and only
// matters as a deliberate kill-switch state. See OPEN QUESTIONS in the PR.
const galleryEnabled = ax.features.enabled(ax.features.PostGalleryEmbedEnable)
const useGallery = galleryEnabled && images.length > GALLERY_IMAGE_THRESHOLD
// Captured from AutoSizedImage so the peek-commit handler can reuse the same
// ref + dims that a tap would — keeps the lightbox's return animation intact.
@@ -109,7 +127,7 @@ export function ImageEmbed({
)
}
if (galleryEnabled) {
if (useGallery) {
return (
<View style={[a.mt_sm, rest.style]}>
<Gallery
+4 -1
View File
@@ -195,7 +195,10 @@ function ComposerReplyToImages({
</View>
</View>
)) ||
(images.length === 4 && (
(images.length >= 4 && (
// Posts can now have up to 10 images, but this is a small 64x64
// thumbnail of the post being replied to, so we cap it at a 2x2
// preview of the first 4 images for anything >=4.
<View style={[a.flex_1, a.gap_2xs]}>
<View style={[a.flex_1, a.flex_row, a.gap_2xs]}>
<Image
+2 -2
View File
@@ -422,7 +422,7 @@ export function SelectMediaButton({
message: `You can select up to ${plural(MAX_IMAGES, {
other: '# images',
})} in total.`,
comment: `Error message for maximum number of images that can be selected to add to a post, currently 4 but may change.`,
comment: `Error message for maximum number of images that can be selected to add to a post. The number is derived from MAX_IMAGES and may change.`,
}),
),
[SelectedAssetError.MaxVideos]: _(
@@ -510,7 +510,7 @@ export function SelectMediaButton({
message: `Opens device gallery to select up to ${plural(MAX_IMAGES, {
other: '# images',
})}, or a single video or GIF.`,
comment: `Accessibility hint for button in composer to add images, a video, or a GIF to a post. Maximum number of images that can be selected is currently 4 but may change.`,
comment: `Accessibility hint for button in composer to add images, a video, or a GIF to a post. The maximum number of images is derived from MAX_IMAGES and may change.`,
}),
)}
style={a.p_sm}
+1 -1
View File
@@ -154,7 +154,7 @@ export type ComposerAction =
draftId: string
}
export const MAX_IMAGES = 4
export const MAX_IMAGES = 10
export function composerReducer(
state: ComposerState,