diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 3b5ddb1dca..0472087f3f 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -363,7 +363,11 @@ let PostThreadItemLoaded = ({
) : undefined}
{post.embed && (
-
+
)}
diff --git a/src/view/com/util/images/AutoSizedImage.tsx b/src/view/com/util/images/AutoSizedImage.tsx
index 61cb6f69f3..9f19b7b32a 100644
--- a/src/view/com/util/images/AutoSizedImage.tsx
+++ b/src/view/com/util/images/AutoSizedImage.tsx
@@ -1,106 +1,152 @@
import React from 'react'
-import {StyleProp, StyleSheet, Pressable, View, ViewStyle} from 'react-native'
+import {Pressable, View} from 'react-native'
import {Image} from 'expo-image'
-import {clamp} from 'lib/numbers'
-import {Dimensions} from 'lib/media/types'
-import * as imageSizes from 'lib/media/image-sizes'
+import {AppBskyEmbedImages} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-const MIN_ASPECT_RATIO = 0.33 // 1/3
-const MAX_ASPECT_RATIO = 10 // 10/1
+import * as imageSizes from '#/lib/media/image-sizes'
+import {Dimensions} from '#/lib/media/types'
+import {atoms as a, useTheme} from '#/alf'
-interface Props {
- alt?: string
- uri: string
- dimensionsHint?: Dimensions
- onPress?: () => void
- onLongPress?: () => void
- onPressIn?: () => void
- style?: StyleProp
- children?: React.ReactNode
+export function useImageAspectRatio({
+ src,
+ dimensions,
+}: {
+ src: string
+ dimensions: Dimensions | undefined
+}) {
+ const [aspectRatio, setAspectRatio] = React.useState(
+ dimensions ? calc(dimensions) : 1,
+ )
+
+ React.useEffect(() => {
+ let aborted = false
+ if (dimensions) return
+ imageSizes.fetch(src).then(newDim => {
+ if (aborted) return
+ setAspectRatio(calc(newDim))
+ })
+ return () => {
+ aborted = true
+ }
+ }, [dimensions, setAspectRatio, src])
+
+ return {
+ dimensions,
+ aspectRatio,
+ }
+}
+
+export function SquareFramedImage({
+ aspectRatio,
+ children,
+}: {
+ aspectRatio: number
+ children: React.ReactNode
+}) {
+ const t = useTheme()
+ const outerAspectRatio = React.useMemo(() => {
+ return Math.min(1 / aspectRatio, 1)
+ }, [aspectRatio])
+ const innerAspectRatio = React.useMemo(() => {
+ return Math.max(aspectRatio, 0.75)
+ }, [aspectRatio])
+
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ )
}
export function AutoSizedImage({
- alt,
- uri,
- dimensionsHint,
+ image,
+ disableCrop,
onPress,
onLongPress,
onPressIn,
- style,
children = null,
-}: Props) {
+}: {
+ image: AppBskyEmbedImages.ViewImage
+ disableCrop?: boolean
+ children?: React.ReactNode
+ onPress?: () => void
+ onLongPress?: () => void
+ onPressIn?: () => void
+}) {
+ const t = useTheme()
const {_} = useLingui()
- const [dim, setDim] = React.useState(
- dimensionsHint || imageSizes.get(uri),
- )
- const [aspectRatio, setAspectRatio] = React.useState(
- dim ? calc(dim) : 1,
- )
- React.useEffect(() => {
- let aborted = false
- if (dim) {
- return
- }
- imageSizes.fetch(uri).then(newDim => {
- if (aborted) {
- return
- }
- setDim(newDim)
- setAspectRatio(calc(newDim))
- })
- }, [dim, setDim, setAspectRatio, uri])
+ const {aspectRatio} = useImageAspectRatio({
+ src: image.thumb,
+ dimensions: image.aspectRatio,
+ })
- if (onPress || onLongPress || onPressIn) {
+ const contents = (
+
+ )
+
+ if (disableCrop) {
return (
- // disable a11y rule because in this case we want the tags on the image (#1640)
- // eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors
-
+ accessibilityLabel={image.alt}
+ accessibilityHint={_(msg`Tap to view fully`)}
+ style={[
+ a.w_full,
+ a.rounded_sm,
+ a.overflow_hidden,
+ t.atoms.bg_contrast_25,
+ {aspectRatio},
+ ]}>
+ {contents}
{children}
)
+ } else {
+ return (
+
+
+ {contents}
+ {children}
+
+
+ )
}
-
- return (
-
-
- {children}
-
- )
}
function calc(dim: Dimensions) {
if (dim.width === 0 || dim.height === 0) {
return 1
}
- return clamp(dim.width / dim.height, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO)
+ return dim.width / dim.height
}
-
-const styles = StyleSheet.create({
- container: {
- overflow: 'hidden',
- },
- image: {
- width: '100%',
- },
-})
diff --git a/src/view/com/util/post-embeds/index.tsx b/src/view/com/util/post-embeds/index.tsx
index d9e075e772..d9932b48cf 100644
--- a/src/view/com/util/post-embeds/index.tsx
+++ b/src/view/com/util/post-embeds/index.tsx
@@ -50,12 +50,14 @@ export function PostEmbeds({
onOpen,
style,
allowNestedQuotes,
+ isHighlightedThreadItem,
}: {
embed?: Embed
moderation?: ModerationDecision
onOpen?: () => void
style?: StyleProp
allowNestedQuotes?: boolean
+ isHighlightedThreadItem?: boolean
}) {
const {openLightbox} = useLightboxControls()
const largeAltBadge = useLargeAltBadgeEnabled()
@@ -124,18 +126,16 @@ export function PostEmbeds({
}
if (images.length === 1) {
- const {alt, thumb, aspectRatio} = images[0]
+ const image = images[0]
return (
_openLightbox(0)}
- onPressIn={() => onPressIn(0)}
- style={a.rounded_sm}>
- {alt === '' ? null : (
+ onPressIn={() => onPressIn(0)}>
+ {image.alt === '' ? null : (