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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -154,7 +154,7 @@ export type ComposerAction =
|
||||
draftId: string
|
||||
}
|
||||
|
||||
export const MAX_IMAGES = 4
|
||||
export const MAX_IMAGES = 10
|
||||
|
||||
export function composerReducer(
|
||||
state: ComposerState,
|
||||
|
||||
Reference in New Issue
Block a user