1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00
This commit is contained in:
xmflsct
2023-02-08 01:10:59 +01:00
parent 9259ee2995
commit d1ed8a0d2a
27 changed files with 176 additions and 563 deletions

View File

@@ -38,7 +38,7 @@ const ComponentAccount: React.FC<PropsWithChildren & Props> = ({ account, props,
<>
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}>
<GracefullyImage
uri={{ original: account.avatar, static: account.avatar_static }}
sources={{ default: { uri: account.avatar }, static: { uri: account.avatar_static } }}
style={{
width: StyleConstants.Avatar.S,
height: StyleConstants.Avatar.S,

View File

@@ -40,7 +40,7 @@ const AccountButton: React.FC<Props> = ({ account, additionalActions }) => {
}}
>
<GracefullyImage
uri={{ original: account.avatar_static }}
sources={{ default: { uri: account.avatar_static } }}
dimension={{
width: StyleConstants.Font.Size.L,
height: StyleConstants.Font.Size.L

View File

@@ -8,6 +8,7 @@ import { getAccountStorage, setAccountStorage } from '@utils/storage/actions'
import { StyleConstants } from '@utils/styles/constants'
import layoutAnimation from '@utils/styles/layoutAnimation'
import { useTheme } from '@utils/styles/ThemeManager'
import { Image } from 'expo-image'
import { chunk } from 'lodash'
import React, { useContext, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
@@ -19,7 +20,6 @@ import {
TextInput,
View
} from 'react-native'
import FastImage from 'react-native-fast-image'
import EmojisContext from './Context'
const EmojisList = () => {
@@ -129,9 +129,7 @@ const EmojisList = () => {
}}
style={{ padding: StyleConstants.Spacing.S }}
>
<FastImage
enterTransition='fadeIn'
transitionDuration={60}
<Image
accessibilityLabel={t('common:customEmoji.accessibilityLabel', {
emoji: emoji.shortcode
})}

View File

@@ -1,36 +1,26 @@
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { connectMedia } from '@utils/api/helpers/connect'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useEffect, useState } from 'react'
import {
AccessibilityProps,
Image,
Pressable,
StyleProp,
StyleSheet,
View,
ViewStyle
} from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import FastImage, { ImageStyle } from 'react-native-fast-image'
// blurhas -> if blurhash, show before any loading succeed
// original -> load original
// original, remote -> if original failed, then remote
// preview, original -> first show preview, then original
// preview, original, remote -> first show preview, then original, if original failed, then remote
import { Image, ImageSource, ImageStyle } from 'expo-image'
import React, { useState } from 'react'
import { AccessibilityProps, Pressable, StyleProp, View, ViewStyle } from 'react-native'
export interface Props {
accessibilityLabel?: AccessibilityProps['accessibilityLabel']
accessibilityHint?: AccessibilityProps['accessibilityHint']
hidden?: boolean
uri: { preview?: string; original?: string; remote?: string; static?: string }
blurhash?: string
sources: {
preview?: ImageSource
default?: ImageSource
remote?: ImageSource
static?: ImageSource
blurhash?: string
}
dimension?: { width: number; height: number }
onPress?: () => void
style?: StyleProp<ViewStyle>
imageStyle?: StyleProp<ImageStyle>
imageStyle?: ImageStyle
// For image viewer when there is no image size available
setImageDimensions?: React.Dispatch<
React.SetStateAction<{
@@ -39,49 +29,30 @@ export interface Props {
}>
>
dim?: boolean
enableLiveTextInteraction?: boolean
}
const GracefullyImage = ({
accessibilityLabel,
accessibilityHint,
hidden = false,
uri,
blurhash,
sources,
dimension,
onPress,
style,
imageStyle,
setImageDimensions,
dim
dim,
enableLiveTextInteraction = false
}: Props) => {
const { reduceMotionEnabled } = useAccessibility()
const { colors, theme } = useTheme()
const [imageLoaded, setImageLoaded] = useState(false)
const { theme } = useTheme()
const [currentUri, setCurrentUri] = useState<string | undefined>(uri.original || uri.remote)
const source: { uri?: string } = {
uri: reduceMotionEnabled && uri.static ? uri.static : currentUri
}
useEffect(() => {
if (
(uri.original ? currentUri !== uri.original : true) &&
(uri.remote ? currentUri !== uri.remote : true)
) {
setCurrentUri(uri.original || uri.remote)
}
}, [currentUri, uri.original, uri.remote])
const blurhashView = () => {
if (hidden || !imageLoaded) {
if (blurhash) {
return <Blurhash decodeAsync blurhash={blurhash} style={styles.placeholder} />
} else {
return <View style={[styles.placeholder, { backgroundColor: colors.shimmerDefault }]} />
}
} else {
return null
}
}
const [currentSource, setCurrentSource] = useState<ImageSource | undefined>(
sources.default || sources.remote
)
const source: ImageSource | undefined =
reduceMotionEnabled && sources.static ? sources.static : currentSource
return (
<Pressable
@@ -91,50 +62,40 @@ const GracefullyImage = ({
style={[style, dimension]}
{...(onPress ? (hidden ? { disabled: true } : { onPress }) : { disabled: true })}
>
{uri.preview && !imageLoaded ? (
<FastImage
source={connectMedia({ uri: uri.preview })}
enterTransition='fadeIn'
transitionDuration={60}
style={[styles.placeholder]}
/>
) : null}
<FastImage
source={connectMedia(source)}
enterTransition={!blurhash && !uri.preview ? 'fadeIn' : 'none'}
transitionDuration={60}
style={[{ flex: 1 }, imageStyle]}
onLoad={() => {
setImageLoaded(true)
if (setImageDimensions && source.uri) {
Image.getSize(source.uri, (width, height) => setImageDimensions({ width, height }))
<Image
placeholder={sources.blurhash || connectMedia(sources.preview)}
source={hidden ? undefined : connectMedia(source)}
transition={{ duration: 100 }}
style={{ flex: 1, ...imageStyle }}
onLoad={event => {
if (setImageDimensions && event.source) {
setImageDimensions(event.source)
}
}}
onError={() => {
if (uri.original && uri.original === currentUri && uri.remote) {
setCurrentUri(uri.remote)
if (
sources.default?.uri &&
sources.default?.uri === currentSource?.uri &&
sources.remote
) {
setCurrentSource(sources.remote)
}
}}
enableLiveTextInteraction={enableLiveTextInteraction}
/>
{blurhashView()}
{dim && theme !== 'light' ? (
<View
style={[
styles.placeholder,
{ backgroundColor: 'black', opacity: theme === 'dark_lighter' ? 0.18 : 0.36 }
]}
style={{
width: '100%',
height: '100%',
position: 'absolute',
backgroundColor: 'black',
opacity: theme === 'dark_lighter' ? 0.18 : 0.36
}}
/>
) : null}
</Pressable>
)
}
const styles = StyleSheet.create({
placeholder: {
width: '100%',
height: '100%',
position: 'absolute'
}
})
export default GracefullyImage

View File

@@ -19,12 +19,13 @@ import {
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import * as AuthSession from 'expo-auth-session'
import { Image } from 'expo-image'
import * as Random from 'expo-random'
import * as WebBrowser from 'expo-web-browser'
import { debounce } from 'lodash'
import React, { RefObject, useCallback, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { Alert, Image, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native'
import { Alert, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { fromByteArray } from 'react-native-quick-base64'
import parse from 'url-parse'

View File

@@ -5,9 +5,9 @@ import { useGlobalStorage } from '@utils/storage/actions'
import { StyleConstants } from '@utils/styles/constants'
import { adaptiveScale } from '@utils/styles/scaling'
import { useTheme } from '@utils/styles/ThemeManager'
import { Image } from 'expo-image'
import React from 'react'
import { ColorValue, Platform, TextStyle } from 'react-native'
import FastImage from 'react-native-fast-image'
const regexEmoji = new RegExp(/(:[A-Za-z0-9_]+:)/)
@@ -77,8 +77,8 @@ const ParseEmojis: React.FC<Props> = ({
return (
<CustomText key={emojiShortcode + i}>
{i === 0 ? ' ' : undefined}
<FastImage
source={connectMedia({ uri: uri.trim() })}
<Image
source={connectMedia({ uri })}
style={{
width: adaptedFontsize,
height: adaptedFontsize,

View File

@@ -79,7 +79,10 @@ const TimelineConversation: React.FC<Props> = ({ conversation, queryKey, highlig
{conversation.accounts.slice(0, 4).map(account => (
<GracefullyImage
key={account.id}
uri={{ original: account.avatar, static: account.avatar_static }}
sources={{
default: { uri: account.avatar },
static: { uri: account.avatar_static }
}}
dimension={{
width: StyleConstants.Avatar.M,
height:

View File

@@ -9,7 +9,6 @@ import { StackNavigationProp } from '@react-navigation/stack'
import { RootStackParamList } from '@utils/navigation/navigators'
import { usePreferencesQuery } from '@utils/queryHooks/preferences'
import { StyleConstants } from '@utils/styles/constants'
import layoutAnimation from '@utils/styles/layoutAnimation'
import React, { useContext, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native'
@@ -207,7 +206,6 @@ const TimelineAttachment = () => {
content={t('shared.attachment.sensitive.button')}
overlay
onPress={() => {
layoutAnimation()
setSensitiveShown(false)
haptics('Light')
}}

View File

@@ -7,7 +7,6 @@ import { useTheme } from '@utils/styles/ThemeManager'
import { Audio } from 'expo-av'
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 { aspectRatio } from './dimensions'
@@ -72,19 +71,23 @@ const AttachmentAudio: React.FC<Props> = ({ total, index, sensitiveShown, audio
<View style={styles.overlay}>
{sensitiveShown ? (
audio.blurhash ? (
<Blurhash
blurhash={audio.blurhash}
<GracefullyImage
sources={{ blurhash: audio.blurhash }}
style={{
width: '100%',
height: '100%'
}}
dim
/>
) : null
) : (
<>
{audio.preview_url ? (
<GracefullyImage
uri={{ original: audio.preview_url, remote: audio.preview_remote_url }}
sources={{
default: { uri: audio.preview_url },
remote: { uri: audio.preview_remote_url }
}}
style={styles.background}
dim
/>

View File

@@ -35,8 +35,11 @@ const AttachmentImage = ({
<GracefullyImage
accessibilityLabel={image.description}
hidden={sensitiveShown}
uri={{ original: image.preview_url, remote: image.remote_url }}
blurhash={image.blurhash}
sources={{
default: { uri: image.preview_url },
remote: { uri: image.remote_url },
blurhash: image.blurhash
}}
onPress={() => navigateToImagesViewer(image.id)}
style={{ aspectRatio: aspectRatio({ total, index, ...image.meta?.original }) }}
dim

View File

@@ -1,4 +1,5 @@
import Button from '@components/Button'
import GracefullyImage from '@components/GracefullyImage'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
@@ -6,7 +7,6 @@ import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import AttachmentAltText from './AltText'
import { aspectRatio } from './dimensions'
@@ -33,8 +33,8 @@ const AttachmentUnsupported: React.FC<Props> = ({ total, index, sensitiveShown,
}}
>
{attachment.blurhash ? (
<Blurhash
blurhash={attachment.blurhash}
<GracefullyImage
sources={{ blurhash: attachment.blurhash }}
style={{
position: 'absolute',
width: '100%',

View File

@@ -1,4 +1,5 @@
import Button from '@components/Button'
import GracefullyImage from '@components/GracefullyImage'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { connectMedia } from '@utils/api/helpers/connect'
import { useAccountStorage, useGlobalStorage } from '@utils/storage/actions'
@@ -8,7 +9,6 @@ import { Platform } from 'expo-modules-core'
import * as ScreenOrientation from 'expo-screen-orientation'
import React, { useRef, useState } from 'react'
import { Pressable, View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import AttachmentAltText from './AltText'
import { aspectRatio } from './dimensions'
@@ -120,7 +120,10 @@ const AttachmentVideo: React.FC<Props> = ({
>
{sensitiveShown ? (
video.blurhash ? (
<Blurhash blurhash={video.blurhash} style={{ width: '100%', height: '100%' }} />
<GracefullyImage
sources={{ blurhash: video.blurhash }}
style={{ width: '100%', height: '100%' }}
/>
) : null
) : !gifv || (gifv && (reduceMotionEnabled || !shouldAutoplayGifv)) ? (
<Button

View File

@@ -33,7 +33,10 @@ const TimelineAvatar: React.FC<Props> = ({ account }) => {
onPress={() =>
!disableOnPress && navigation.push('Tab-Shared-Account', { account: actualAccount })
}
uri={{ original: actualAccount.avatar, static: actualAccount.avatar_static }}
sources={{
default: { uri: actualAccount.avatar },
static: { uri: actualAccount.avatar_static }
}}
dimension={
disableDetails || isConversation
? {

View File

@@ -82,8 +82,7 @@ const TimelineCard: React.FC = () => {
<>
{status.card?.image ? (
<GracefullyImage
uri={{ original: status.card.image }}
blurhash={status.card.blurhash}
sources={{ default: { uri: status.card.image }, blurhash: status.card.blurhash }}
style={{ flexBasis: StyleConstants.Font.LineHeight.M * 5 }}
imageStyle={{ borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }}
dim