Assuming most toot won't include more than 4 images. For below 4 images, mostly they are not cropped unless they are too long. For single image, mostly it is not cropped unless it is longer than 3/2.
This commit is contained in:
xmflsct 2022-12-12 22:24:03 +01:00
parent 91be219ff3
commit 96497aad25
7 changed files with 73 additions and 47 deletions

View File

@ -45,6 +45,21 @@ const TimelineAttachment = () => {
}
const [sensitiveShown, setSensitiveShown] = useState(defaultSensitive())
// const testHorizontal: Mastodon.Attachment[] = Array(2).fill({
// id: Math.random().toString(),
// type: 'image',
// url: 'https://images.unsplash.com/photo-1670870764013-f0e36aa376b0?w=1000',
// preview_url: 'https://images.unsplash.com/photo-1543968996-ee822b8176ba?w=300',
// meta: { original: { width: 1000, height: 625 } }
// })
// const testVertical: Mastodon.Attachment[] = Array(7).fill({
// id: Math.random().toString(),
// type: 'image',
// url: 'https://images.unsplash.com/photo-1670842587871-326b95acbc8c?w=1000',
// preview_url: 'https://images.unsplash.com/photo-1670833288990-64b2f4ef7290?w=300',
// meta: { original: { width: 987, height: 1480 } }
// })
// @ts-ignore
const imageUrls: RootStackParamList['Screen-ImagesViewer']['imageUrls'] = status.media_attachments
.map(attachment => {

View File

@ -8,7 +8,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'
import { AppState, AppStateStatus, StyleSheet, View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import AttachmentAltText from './AltText'
import attachmentAspectRatio from './aspectRatio'
import { aspectRatio } from './dimensions'
export interface Props {
total: number
@ -64,7 +64,7 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio
styles.base,
{
backgroundColor: colors.disabled,
aspectRatio: attachmentAspectRatio({ total, index })
aspectRatio: aspectRatio({ total, index, ...audio.meta?.original })
}
]}
>

View File

@ -1,9 +1,10 @@
import GracefullyImage from '@components/GracefullyImage'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { View } from 'react-native'
import AttachmentAltText from './AltText'
import attachmentAspectRatio from './aspectRatio'
import { aspectRatio } from './dimensions'
export interface Props {
total: number
@ -20,6 +21,8 @@ const AttachmentImage = ({
image,
navigateToImagesViewer
}: Props) => {
const { colors } = useTheme()
return (
<View
style={{
@ -28,21 +31,16 @@ const AttachmentImage = ({
padding: StyleConstants.Spacing.XS / 2
}}
>
<GracefullyImage
accessibilityLabel={image.description}
hidden={sensitiveShown}
uri={{ original: image.preview_url, remote: image.remote_url }}
blurhash={image.blurhash}
onPress={() => navigateToImagesViewer(image.id)}
style={{
aspectRatio:
total > 1 || !image.meta?.original?.width || !image.meta?.original?.height
? attachmentAspectRatio({ total, index })
: image.meta.original.height / image.meta.original.width > 1
? 1
: image.meta.original.width / image.meta.original.height
}}
/>
<View style={{ flex: 1, backgroundColor: colors.shimmerDefault }}>
<GracefullyImage
accessibilityLabel={image.description}
hidden={sensitiveShown}
uri={{ original: image.preview_url, remote: image.remote_url }}
blurhash={image.blurhash}
onPress={() => navigateToImagesViewer(image.id)}
style={{ aspectRatio: aspectRatio({ total, index, ...image.meta?.original }) }}
/>
</View>
<AttachmentAltText sensitiveShown={sensitiveShown} text={image.description} />
</View>
)

View File

@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next'
import { View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import AttachmentAltText from './AltText'
import attachmentAspectRatio from './aspectRatio'
import { aspectRatio } from './dimensions'
export interface Props {
total: number
@ -29,7 +29,7 @@ const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown,
padding: StyleConstants.Spacing.XS / 2,
justifyContent: 'center',
alignItems: 'center',
aspectRatio: attachmentAspectRatio({ total, index })
aspectRatio: aspectRatio({ total, index, ...attachment.meta?.original })
}}
>
{attachment.blurhash ? (

View File

@ -4,10 +4,10 @@ import { ResizeMode, Video, VideoFullscreenUpdate } from 'expo-av'
import React, { useRef, useState } from 'react'
import { Pressable, View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import attachmentAspectRatio from './aspectRatio'
import AttachmentAltText from './AltText'
import { Platform } from 'expo-modules-core'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { aspectRatio } from './dimensions'
export interface Props {
total: number
@ -49,7 +49,7 @@ const AttachmentVideo: React.FC<Props> = ({
flex: 1,
flexBasis: '50%',
padding: StyleConstants.Spacing.XS / 2,
aspectRatio: attachmentAspectRatio({ total, index })
aspectRatio: aspectRatio({ total, index, ...video.meta?.original })
}}
>
<Video

View File

@ -1,25 +0,0 @@
const attachmentAspectRatio = ({
total,
index
}: {
total: number
index?: number
}) => {
switch (total) {
case 1:
case 4:
return 16 / 9
case 2:
return 8 / 9
case 3:
if (index === 2) {
return 32 / 9
} else {
return 16 / 9
}
default:
return 16 / 9
}
}
export default attachmentAspectRatio

View File

@ -0,0 +1,38 @@
export const aspectRatio = ({
total,
index,
width,
height
}: {
total: number
index?: number
width?: number
height?: number
}): number => {
const cropTooTall = (height || 1) / (width || 1) > 3 / 2 ? 2 / 3 : (width || 1) / (height || 1)
const isEven = total % 2 == 0
if (total > 5) {
switch (isEven) {
case true:
return total / 2 / 2
case false:
if ((index || -2) + 1 == total) {
return Math.ceil(total / 2)
} else {
return Math.ceil(total / 2) / 2
}
}
} else {
switch (isEven) {
case true:
return cropTooTall
case false:
if ((index || -2) + 1 == total) {
return cropTooTall * 2
} else {
return cropTooTall
}
}
}
}