mirror of https://github.com/tooot-app/app
Prevent image loading flashing in conversation
This commit is contained in:
parent
d2eb7156a4
commit
73e4bdb290
|
@ -23,6 +23,7 @@ export interface Props {
|
||||||
imageStyle?: ImageStyle
|
imageStyle?: ImageStyle
|
||||||
|
|
||||||
dim?: boolean
|
dim?: boolean
|
||||||
|
withoutTransition?: boolean
|
||||||
enableLiveTextInteraction?: boolean
|
enableLiveTextInteraction?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ const GracefullyImage = ({
|
||||||
style,
|
style,
|
||||||
imageStyle,
|
imageStyle,
|
||||||
dim,
|
dim,
|
||||||
|
withoutTransition = false,
|
||||||
enableLiveTextInteraction = false
|
enableLiveTextInteraction = false
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { reduceMotionEnabled } = useAccessibility()
|
const { reduceMotionEnabled } = useAccessibility()
|
||||||
|
@ -59,7 +61,7 @@ const GracefullyImage = ({
|
||||||
placeholderContentFit='cover'
|
placeholderContentFit='cover'
|
||||||
placeholder={sources.blurhash || connectMedia(sources.preview)}
|
placeholder={sources.blurhash || connectMedia(sources.preview)}
|
||||||
source={hidden ? undefined : connectMedia(source)}
|
source={hidden ? undefined : connectMedia(source)}
|
||||||
transition={{ duration: 80 }}
|
{...((!withoutTransition || !reduceMotionEnabled) && { transition: { duration: 120 } })}
|
||||||
style={{ flex: 1, ...imageStyle }}
|
style={{ flex: 1, ...imageStyle }}
|
||||||
onError={() => {
|
onError={() => {
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -5,8 +5,9 @@ import { connectMedia } from '@utils/api/helpers/connect'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import { Audio } from 'expo-av'
|
import { Audio } from 'expo-av'
|
||||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'
|
||||||
import { AppState, AppStateStatus, View } from 'react-native'
|
import { AppState, AppStateStatus, View } from 'react-native'
|
||||||
|
import StatusContext from '../Context'
|
||||||
import AttachmentAltText from './AltText'
|
import AttachmentAltText from './AltText'
|
||||||
import { aspectRatio } from './dimensions'
|
import { aspectRatio } from './dimensions'
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio }) => {
|
const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio }) => {
|
||||||
|
const { inThread } = useContext(StatusContext)
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const [audioPlayer, setAudioPlayer] = useState<Audio.Sound>()
|
const [audioPlayer, setAudioPlayer] = useState<Audio.Sound>()
|
||||||
|
@ -88,6 +90,7 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio
|
||||||
height: '100%'
|
height: '100%'
|
||||||
}}
|
}}
|
||||||
dim
|
dim
|
||||||
|
withoutTransition={inThread}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
) : (
|
) : (
|
||||||
|
@ -100,6 +103,7 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio
|
||||||
}}
|
}}
|
||||||
style={{ position: 'absolute', width: '100%', height: '100%' }}
|
style={{ position: 'absolute', width: '100%', height: '100%' }}
|
||||||
dim
|
dim
|
||||||
|
withoutTransition={inThread}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import GracefullyImage from '@components/GracefullyImage'
|
import GracefullyImage from '@components/GracefullyImage'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React from 'react'
|
import React, { useContext } from 'react'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
|
import StatusContext from '../Context'
|
||||||
import AttachmentAltText from './AltText'
|
import AttachmentAltText from './AltText'
|
||||||
import { aspectRatio } from './dimensions'
|
import { aspectRatio } from './dimensions'
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ const AttachmentImage = ({
|
||||||
image,
|
image,
|
||||||
navigateToImagesViewer
|
navigateToImagesViewer
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const { inThread } = useContext(StatusContext)
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -45,6 +47,7 @@ const AttachmentImage = ({
|
||||||
onPress={() => navigateToImagesViewer(image.id)}
|
onPress={() => navigateToImagesViewer(image.id)}
|
||||||
style={{ aspectRatio: aspectRatio({ total, index, ...image.meta?.original }) }}
|
style={{ aspectRatio: aspectRatio({ total, index, ...image.meta?.original }) }}
|
||||||
dim
|
dim
|
||||||
|
withoutTransition={inThread}
|
||||||
/>
|
/>
|
||||||
<AttachmentAltText sensitiveShown={sensitiveShown} text={image.description} />
|
<AttachmentAltText sensitiveShown={sensitiveShown} text={image.description} />
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -4,9 +4,10 @@ import openLink from '@components/openLink'
|
||||||
import CustomText from '@components/Text'
|
import CustomText from '@components/Text'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React from 'react'
|
import React, { useContext } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
|
import StatusContext from '../Context'
|
||||||
import AttachmentAltText from './AltText'
|
import AttachmentAltText from './AltText'
|
||||||
import { aspectRatio } from './dimensions'
|
import { aspectRatio } from './dimensions'
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown, attachment }) => {
|
const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown, attachment }) => {
|
||||||
|
const { inThread } = useContext(StatusContext)
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
|
@ -36,6 +38,8 @@ const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown,
|
||||||
<GracefullyImage
|
<GracefullyImage
|
||||||
sources={{ blurhash: attachment.blurhash }}
|
sources={{ blurhash: attachment.blurhash }}
|
||||||
style={{ position: 'absolute', width: '100%', height: '100%' }}
|
style={{ position: 'absolute', width: '100%', height: '100%' }}
|
||||||
|
dim
|
||||||
|
withoutTransition={inThread}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{!sensitiveShown ? (
|
{!sensitiveShown ? (
|
||||||
|
|
|
@ -8,8 +8,9 @@ import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import { ResizeMode, Video, VideoFullscreenUpdate } from 'expo-av'
|
import { ResizeMode, Video, VideoFullscreenUpdate } from 'expo-av'
|
||||||
import { Platform } from 'expo-modules-core'
|
import { Platform } from 'expo-modules-core'
|
||||||
import * as ScreenOrientation from 'expo-screen-orientation'
|
import * as ScreenOrientation from 'expo-screen-orientation'
|
||||||
import React, { useRef, useState } from 'react'
|
import React, { useContext, useRef, useState } from 'react'
|
||||||
import { Pressable, View } from 'react-native'
|
import { Pressable, View } from 'react-native'
|
||||||
|
import StatusContext from '../Context'
|
||||||
import AttachmentAltText from './AltText'
|
import AttachmentAltText from './AltText'
|
||||||
import { aspectRatio } from './dimensions'
|
import { aspectRatio } from './dimensions'
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ const AttachmentVideo: React.FC<Props> = ({
|
||||||
video,
|
video,
|
||||||
gifv = false
|
gifv = false
|
||||||
}) => {
|
}) => {
|
||||||
|
const { inThread } = useContext(StatusContext)
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { reduceMotionEnabled } = useAccessibility()
|
const { reduceMotionEnabled } = useAccessibility()
|
||||||
const [shouldAutoplayGifv] = useGlobalStorage.boolean('app.auto_play_gifv')
|
const [shouldAutoplayGifv] = useGlobalStorage.boolean('app.auto_play_gifv')
|
||||||
|
@ -127,6 +129,8 @@ const AttachmentVideo: React.FC<Props> = ({
|
||||||
<GracefullyImage
|
<GracefullyImage
|
||||||
sources={{ blurhash: video.blurhash }}
|
sources={{ blurhash: video.blurhash }}
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
dim
|
||||||
|
withoutTransition={inThread}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
) : !gifv || (gifv && (reduceMotionEnabled || !shouldAutoplayGifv)) ? (
|
) : !gifv || (gifv && (reduceMotionEnabled || !shouldAutoplayGifv)) ? (
|
||||||
|
|
|
@ -12,7 +12,7 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimelineAvatar: React.FC<Props> = ({ account }) => {
|
const TimelineAvatar: React.FC<Props> = ({ account }) => {
|
||||||
const { status, highlighted, disableDetails, disableOnPress, isConversation } =
|
const { status, highlighted, disableDetails, disableOnPress, isConversation, inThread } =
|
||||||
useContext(StatusContext)
|
useContext(StatusContext)
|
||||||
const actualAccount = account || status?.account
|
const actualAccount = account || status?.account
|
||||||
if (!actualAccount) return null
|
if (!actualAccount) return null
|
||||||
|
@ -54,6 +54,7 @@ const TimelineAvatar: React.FC<Props> = ({ account }) => {
|
||||||
marginRight: StyleConstants.Spacing.S
|
marginRight: StyleConstants.Spacing.S
|
||||||
}}
|
}}
|
||||||
dim
|
dim
|
||||||
|
withoutTransition={inThread}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import TimelineDefault from '../Default'
|
||||||
import StatusContext from './Context'
|
import StatusContext from './Context'
|
||||||
|
|
||||||
const TimelineCard: React.FC = () => {
|
const TimelineCard: React.FC = () => {
|
||||||
const { status, spoilerHidden, disableDetails } = useContext(StatusContext)
|
const { status, spoilerHidden, disableDetails, inThread } = useContext(StatusContext)
|
||||||
if (!status || !status.card) return null
|
if (!status || !status.card) return null
|
||||||
|
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
@ -86,6 +86,7 @@ const TimelineCard: React.FC = () => {
|
||||||
style={{ flexBasis: StyleConstants.Font.LineHeight.M * 5 }}
|
style={{ flexBasis: StyleConstants.Font.LineHeight.M * 5 }}
|
||||||
imageStyle={{ borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }}
|
imageStyle={{ borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }}
|
||||||
dim
|
dim
|
||||||
|
withoutTransition={inThread}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<View style={{ flex: 1, padding: StyleConstants.Spacing.S }}>
|
<View style={{ flex: 1, padding: StyleConstants.Spacing.S }}>
|
||||||
|
|
Loading…
Reference in New Issue