diff options
Diffstat (limited to 'src/view/com/util/images/AutoSizedImage.tsx')
-rw-r--r-- | src/view/com/util/images/AutoSizedImage.tsx | 67 |
1 files changed, 30 insertions, 37 deletions
diff --git a/src/view/com/util/images/AutoSizedImage.tsx b/src/view/com/util/images/AutoSizedImage.tsx index 21f6c529e..c26df8335 100644 --- a/src/view/com/util/images/AutoSizedImage.tsx +++ b/src/view/com/util/images/AutoSizedImage.tsx @@ -6,8 +6,7 @@ import {AppBskyEmbedImages} from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {useImageDimensions} from '#/lib/media/image-sizes' -import {Dimensions} from '#/lib/media/types' +import type {Dimensions} from '#/lib/media/types' import {isNative} from '#/platform/detection' import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' import {atoms as a, useBreakpoints, useTheme} from '#/alf' @@ -15,30 +14,6 @@ import {ArrowsDiagonalOut_Stroke2_Corner0_Rounded as Fullscreen} from '#/compone import {MediaInsetBorder} from '#/components/MediaInsetBorder' import {Text} from '#/components/Typography' -function useImageAspectRatio({ - src, - knownDimensions, -}: { - src: string - knownDimensions: Dimensions | null -}) { - const [raw] = useImageDimensions({src, knownDimensions}) - let constrained: number | undefined - let max: number | undefined - let isCropped: boolean | undefined - if (raw !== undefined) { - const ratio = 1 / 2 // max of 1:2 ratio in feeds - constrained = Math.max(raw, ratio) - max = Math.max(raw, 0.25) // max of 1:4 in thread - isCropped = raw < constrained - } - return { - constrained, - max, - isCropped, - } -} - export function ConstrainedImage({ aspectRatio, fullBleed, @@ -93,23 +68,38 @@ export function AutoSizedImage({ image: AppBskyEmbedImages.ViewImage crop?: 'none' | 'square' | 'constrained' hideBadge?: boolean - onPress?: (containerRef: AnimatedRef<React.Component<{}, {}, any>>) => void + onPress?: ( + containerRef: AnimatedRef<React.Component<{}, {}, any>>, + fetchedDims: Dimensions | null, + ) => void onLongPress?: () => void onPressIn?: () => void }) { const t = useTheme() const {_} = useLingui() const largeAlt = useLargeAltBadgeEnabled() - const { - constrained, - max, - isCropped: rawIsCropped, - } = useImageAspectRatio({ - src: image.thumb, - knownDimensions: image.aspectRatio ?? null, - }) const containerRef = useAnimatedRef() + const [fetchedDims, setFetchedDims] = React.useState<Dimensions | null>(null) + const dims = fetchedDims ?? image.aspectRatio + let aspectRatio: number | undefined + if (dims) { + aspectRatio = dims.width / dims.height + if (Number.isNaN(aspectRatio)) { + aspectRatio = undefined + } + } + + let constrained: number | undefined + let max: number | undefined + let rawIsCropped: boolean | undefined + if (aspectRatio !== undefined) { + const ratio = 1 / 2 // max of 1:2 ratio in feeds + constrained = Math.max(aspectRatio, ratio) + max = Math.max(aspectRatio, 0.25) // max of 1:4 in thread + rawIsCropped = aspectRatio < constrained + } + const cropDisabled = crop === 'none' const isCropped = rawIsCropped && !cropDisabled const hasAlt = !!image.alt @@ -123,6 +113,9 @@ export function AutoSizedImage({ accessibilityIgnoresInvertColors accessibilityLabel={image.alt} accessibilityHint="" + onLoad={e => { + setFetchedDims({width: e.source.width, height: e.source.height}) + }} /> <MediaInsetBorder /> @@ -194,7 +187,7 @@ export function AutoSizedImage({ if (cropDisabled) { return ( <Pressable - onPress={() => onPress?.(containerRef)} + onPress={() => onPress?.(containerRef, fetchedDims)} onLongPress={onLongPress} onPressIn={onPressIn} // alt here is what screen readers actually use @@ -216,7 +209,7 @@ export function AutoSizedImage({ fullBleed={crop === 'square'} aspectRatio={constrained ?? 1}> <Pressable - onPress={() => onPress?.(containerRef)} + onPress={() => onPress?.(containerRef, fetchedDims)} onLongPress={onLongPress} onPressIn={onPressIn} // alt here is what screen readers actually use |