ce686fae89
Thread onPreviewPress(index) through ImageLayoutGrid / GalleryItem and the Gallery scroll item so multi-image embeds get the same iOS peek behaviour as single-image embeds. Each grid cell wraps its Pressable in ImageContextMenu with the image's true aspect ratio, so the preview lifts to the full uncropped image even when the cell is cropped to square. https://claude.ai/code/session_015REmux3R9uuEMMJUHxTyQT
78 lines
2.4 KiB
TypeScript
78 lines
2.4 KiB
TypeScript
import {type ReactNode} from 'react'
|
|
import {type StyleProp, type ViewStyle} from 'react-native'
|
|
import {msg} from '@lingui/core/macro'
|
|
import {useLingui} from '@lingui/react'
|
|
|
|
import {shareImageModal} from '#/lib/media/manip'
|
|
import {useSaveImageToMediaLibrary} from '#/lib/media/save-image'
|
|
import {ArrowShareRight_Stroke2_Corner2_Rounded as ShareIcon} from '#/components/icons/ArrowShareRight'
|
|
import {Download_Stroke2_Corner0_Rounded as DownloadIcon} from '#/components/icons/Download'
|
|
import {IS_IOS} from '#/env'
|
|
import * as ContextMenu from '../../../../modules/expo-bluesky-context-menu'
|
|
|
|
/**
|
|
* Wraps an image embed with the iOS peek-and-menu interaction. On non-iOS
|
|
* platforms this renders children unchanged.
|
|
*
|
|
* The aspect ratio is consumed by the native side to size the preview
|
|
* viewController correctly — which is what makes the lift animation clean
|
|
* for portrait/panorama images.
|
|
*/
|
|
export function ImageContextMenu({
|
|
fullsizeUri,
|
|
aspectRatio,
|
|
borderRadius,
|
|
onPreviewPress,
|
|
style,
|
|
children,
|
|
}: {
|
|
fullsizeUri: string
|
|
/** width / height; defaults to 1 if missing. */
|
|
aspectRatio: number | undefined
|
|
borderRadius?: number
|
|
onPreviewPress?: () => void
|
|
style?: StyleProp<ViewStyle>
|
|
children: ReactNode
|
|
}) {
|
|
const {_} = useLingui()
|
|
const saveImage = useSaveImageToMediaLibrary()
|
|
|
|
if (!IS_IOS) {
|
|
return children
|
|
}
|
|
|
|
const handleSave = () => {
|
|
void saveImage(fullsizeUri)
|
|
}
|
|
const handleShare = () => {
|
|
void shareImageModal({uri: fullsizeUri})
|
|
}
|
|
|
|
return (
|
|
<ContextMenu.Root style={style}>
|
|
<ContextMenu.Trigger
|
|
preview={{
|
|
type: 'image',
|
|
uri: fullsizeUri,
|
|
aspectRatio: aspectRatio && aspectRatio > 0 ? aspectRatio : 1,
|
|
}}
|
|
borderRadius={borderRadius}
|
|
onPreviewPress={onPreviewPress}>
|
|
{children}
|
|
</ContextMenu.Trigger>
|
|
<ContextMenu.Menu>
|
|
<ContextMenu.MenuItem id="save" onSelect={handleSave}>
|
|
<ContextMenu.MenuItemIcon icon={DownloadIcon} />
|
|
<ContextMenu.MenuItemText>
|
|
{_(msg`Save image`)}
|
|
</ContextMenu.MenuItemText>
|
|
</ContextMenu.MenuItem>
|
|
<ContextMenu.MenuItem id="share" onSelect={handleShare}>
|
|
<ContextMenu.MenuItemIcon icon={ShareIcon} />
|
|
<ContextMenu.MenuItemText>{_(msg`Share`)}</ContextMenu.MenuItemText>
|
|
</ContextMenu.MenuItem>
|
|
</ContextMenu.Menu>
|
|
</ContextMenu.Root>
|
|
)
|
|
}
|