Add <DeferReveal> to defer expensive views
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import {ReactNode, useEffect, useState} from 'react'
|
||||
|
||||
export function DeferReveal({
|
||||
children,
|
||||
defer,
|
||||
// To verify, toggle `forceReveal` between `true` and `false`.
|
||||
iVerifiedThereAreNoLayoutJumps: _unused,
|
||||
forceReveal,
|
||||
}: {
|
||||
children: ReactNode
|
||||
defer: boolean
|
||||
iVerifiedThereAreNoLayoutJumps: true
|
||||
forceReveal?: never // DEV-only
|
||||
}) {
|
||||
const [isReady, setIsReady] = useState(!defer)
|
||||
useEffect(() => {
|
||||
if (!isReady) {
|
||||
setIsReady(true)
|
||||
}
|
||||
}, [isReady])
|
||||
const finalIsReady = forceReveal ?? isReady
|
||||
return finalIsReady ? children : null
|
||||
}
|
||||
@@ -8,8 +8,10 @@ import {useLingui} from '@lingui/react'
|
||||
import {HandleRef, useHandleRef} from '#/lib/hooks/useHandleRef'
|
||||
import type {Dimensions} from '#/lib/media/types'
|
||||
import {isNative} from '#/platform/detection'
|
||||
import {isAndroid} from '#/platform/detection'
|
||||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||
import {DeferReveal} from '#/components/DeferReveal'
|
||||
import {ArrowsDiagonalOut_Stroke2_Corner0_Rounded as Fullscreen} from '#/components/icons/ArrowsDiagonal'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {Text} from '#/components/Typography'
|
||||
@@ -107,6 +109,7 @@ export function AutoSizedImage({
|
||||
|
||||
const contents = (
|
||||
<View ref={containerRef} collapsable={false} style={{flex: 1}}>
|
||||
<DeferReveal defer={isAndroid} iVerifiedThereAreNoLayoutJumps>
|
||||
<Image
|
||||
style={[a.w_full, a.h_full]}
|
||||
source={image.thumb}
|
||||
@@ -185,6 +188,7 @@ export function AutoSizedImage({
|
||||
)}
|
||||
</View>
|
||||
) : null}
|
||||
</DeferReveal>
|
||||
</View>
|
||||
)
|
||||
|
||||
|
||||
@@ -7,9 +7,11 @@ import {useLingui} from '@lingui/react'
|
||||
|
||||
import {HandleRef} from '#/lib/hooks/useHandleRef'
|
||||
import {Dimensions} from '#/lib/media/types'
|
||||
import {isAndroid} from '#/platform/detection'
|
||||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||
import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {DeferReveal} from '#/components/DeferReveal'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
@@ -70,6 +72,7 @@ export function GalleryItem({
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={image.alt || _(msg`Image`)}
|
||||
accessibilityHint="">
|
||||
<DeferReveal defer={isAndroid} iVerifiedThereAreNoLayoutJumps>
|
||||
<Image
|
||||
source={{uri: image.thumb}}
|
||||
style={[a.flex_1]}
|
||||
@@ -84,6 +87,7 @@ export function GalleryItem({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</DeferReveal>
|
||||
<MediaInsetBorder style={insetBorderStyle} />
|
||||
</Pressable>
|
||||
{hasAlt && !hideBadges ? (
|
||||
|
||||
@@ -9,12 +9,13 @@ import {parseAltFromGIFDescription} from '#/lib/gif-alt-text'
|
||||
import {shareUrl} from '#/lib/sharing'
|
||||
import {parseEmbedPlayerFromUrl} from '#/lib/strings/embed-player'
|
||||
import {toNiceDomain} from '#/lib/strings/url-helpers'
|
||||
import {isNative} from '#/platform/detection'
|
||||
import {isAndroid, isNative} from '#/platform/detection'
|
||||
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
||||
import {ExternalGifEmbed} from '#/view/com/util/post-embeds/ExternalGifEmbed'
|
||||
import {ExternalPlayer} from '#/view/com/util/post-embeds/ExternalPlayerEmbed'
|
||||
import {GifEmbed} from '#/view/com/util/post-embeds/GifEmbed'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {DeferReveal} from '#/components/DeferReveal'
|
||||
import {Divider} from '#/components/Divider'
|
||||
import {Earth_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe'
|
||||
import {Link} from '#/components/Link'
|
||||
@@ -87,13 +88,18 @@ export const ExternalLinkEmbed = ({
|
||||
: t.atoms.border_contrast_low,
|
||||
]}>
|
||||
{imageUri && !embedPlayerParams ? (
|
||||
<Image
|
||||
<View
|
||||
style={{
|
||||
aspectRatio: 1.91,
|
||||
}}
|
||||
}}>
|
||||
<DeferReveal defer={isAndroid} iVerifiedThereAreNoLayoutJumps>
|
||||
<Image
|
||||
style={{flex: 1}}
|
||||
source={{uri: imageUri}}
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
</DeferReveal>
|
||||
</View>
|
||||
) : undefined}
|
||||
|
||||
{embedPlayerParams?.isGif ? (
|
||||
|
||||
@@ -23,9 +23,10 @@ import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
import {NavigationProp} from '#/lib/routes/types'
|
||||
import {EmbedPlayerParams, getPlayerAspect} from '#/lib/strings/embed-player'
|
||||
import {isNative} from '#/platform/detection'
|
||||
import {isAndroid, isNative} from '#/platform/detection'
|
||||
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {DeferReveal} from '#/components/DeferReveal'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {EmbedConsentDialog} from '#/components/dialogs/EmbedConsent'
|
||||
import {Fill} from '#/components/Fill'
|
||||
@@ -217,6 +218,7 @@ export function ExternalPlayer({
|
||||
ref={viewRef}
|
||||
collapsable={false}
|
||||
style={[aspect, a.overflow_hidden]}>
|
||||
<DeferReveal defer={isAndroid} iVerifiedThereAreNoLayoutJumps>
|
||||
{link.thumb && (!isPlayerActive || isLoading) ? (
|
||||
<>
|
||||
<Image
|
||||
@@ -254,6 +256,7 @@ export function ExternalPlayer({
|
||||
params={params}
|
||||
onLoad={onLoad}
|
||||
/>
|
||||
</DeferReveal>
|
||||
</Animated.View>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -12,10 +12,11 @@ import {useLingui} from '@lingui/react'
|
||||
|
||||
import {HITSLOP_20} from '#/lib/constants'
|
||||
import {EmbedPlayerParams} from '#/lib/strings/embed-player'
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {isAndroid, isWeb} from '#/platform/detection'
|
||||
import {useAutoplayDisabled} from '#/state/preferences'
|
||||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {DeferReveal} from '#/components/DeferReveal'
|
||||
import {Fill} from '#/components/Fill'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
@@ -121,6 +122,7 @@ export function GifEmbed({
|
||||
{aspectRatio: params.dimensions!.width / params.dimensions!.height},
|
||||
style,
|
||||
]}>
|
||||
<DeferReveal defer={isAndroid} iVerifiedThereAreNoLayoutJumps>
|
||||
<View
|
||||
style={[
|
||||
a.absolute,
|
||||
@@ -161,6 +163,7 @@ export function GifEmbed({
|
||||
)}
|
||||
{!hideAlt && isPreferredAltText && <AltText text={altText} />}
|
||||
</View>
|
||||
</DeferReveal>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user