mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at tmp-rm-bitdrift 147 lines 4.4 kB view raw
1import React from 'react' 2import {ActivityIndicator, GestureResponderEvent, Pressable} from 'react-native' 3import {Image} from 'expo-image' 4import {AppBskyEmbedExternal} from '@atproto/api' 5import {msg} from '@lingui/macro' 6import {useLingui} from '@lingui/react' 7 8import {EmbedPlayerParams} from '#/lib/strings/embed-player' 9import {isIOS, isNative, isWeb} from '#/platform/detection' 10import {useExternalEmbedsPrefs} from '#/state/preferences' 11import {atoms as a, useTheme} from '#/alf' 12import {useDialogControl} from '#/components/Dialog' 13import {EmbedConsentDialog} from '#/components/dialogs/EmbedConsent' 14import {Fill} from '#/components/Fill' 15import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' 16 17export function ExternalGifEmbed({ 18 link, 19 params, 20}: { 21 link: AppBskyEmbedExternal.ViewExternal 22 params: EmbedPlayerParams 23}) { 24 const t = useTheme() 25 const externalEmbedsPrefs = useExternalEmbedsPrefs() 26 const {_} = useLingui() 27 const consentDialogControl = useDialogControl() 28 29 // Tracking if the placer has been activated 30 const [isPlayerActive, setIsPlayerActive] = React.useState(false) 31 // Tracking whether the gif has been loaded yet 32 const [isPrefetched, setIsPrefetched] = React.useState(false) 33 // Tracking whether the image is animating 34 const [isAnimating, setIsAnimating] = React.useState(true) 35 36 // Used for controlling animation 37 const imageRef = React.useRef<Image>(null) 38 39 const load = React.useCallback(() => { 40 setIsPlayerActive(true) 41 Image.prefetch(params.playerUri).then(() => { 42 // Replace the image once it's fetched 43 setIsPrefetched(true) 44 }) 45 }, [params.playerUri]) 46 47 const onPlayPress = React.useCallback( 48 (event: GestureResponderEvent) => { 49 // Don't propagate on web 50 event.preventDefault() 51 52 // Show consent if this is the first load 53 if (externalEmbedsPrefs?.[params.source] === undefined) { 54 consentDialogControl.open() 55 return 56 } 57 // If the player isn't active, we want to activate it and prefetch the gif 58 if (!isPlayerActive) { 59 load() 60 return 61 } 62 // Control animation on native 63 setIsAnimating(prev => { 64 if (prev) { 65 if (isNative) { 66 imageRef.current?.stopAnimating() 67 } 68 return false 69 } else { 70 if (isNative) { 71 imageRef.current?.startAnimating() 72 } 73 return true 74 } 75 }) 76 }, 77 [ 78 consentDialogControl, 79 externalEmbedsPrefs, 80 isPlayerActive, 81 load, 82 params.source, 83 ], 84 ) 85 86 return ( 87 <> 88 <EmbedConsentDialog 89 control={consentDialogControl} 90 source={params.source} 91 onAccept={load} 92 /> 93 94 <Pressable 95 style={[ 96 {height: 300}, 97 a.w_full, 98 a.overflow_hidden, 99 { 100 borderBottomLeftRadius: 0, 101 borderBottomRightRadius: 0, 102 }, 103 ]} 104 onPress={onPlayPress} 105 accessibilityRole="button" 106 accessibilityHint={_(msg`Plays the GIF`)} 107 accessibilityLabel={_(msg`Play ${link.title}`)}> 108 <Image 109 source={{ 110 uri: 111 !isPrefetched || (isWeb && !isAnimating) 112 ? link.thumb 113 : params.playerUri, 114 }} // Web uses the thumb to control playback 115 style={{flex: 1}} 116 ref={imageRef} 117 autoplay={isAnimating} 118 contentFit="contain" 119 accessibilityIgnoresInvertColors 120 accessibilityLabel={link.title} 121 accessibilityHint={link.title} 122 cachePolicy={isIOS ? 'disk' : 'memory-disk'} // cant control playback with memory-disk on ios 123 /> 124 125 {(!isPrefetched || !isAnimating) && ( 126 <Fill style={[a.align_center, a.justify_center]}> 127 <Fill 128 style={[ 129 t.name === 'light' ? t.atoms.bg_contrast_975 : t.atoms.bg, 130 { 131 opacity: 0.3, 132 }, 133 ]} 134 /> 135 136 {!isAnimating || !isPlayerActive ? ( // Play button when not animating or not active 137 <PlayButtonIcon /> 138 ) : ( 139 // Activity indicator while gif loads 140 <ActivityIndicator size="large" color="white" /> 141 )} 142 </Fill> 143 )} 144 </Pressable> 145 </> 146 ) 147}