Bluesky app fork with some witchin' additions 馃挮
at main 136 lines 3.4 kB view raw
1import { 2 ActivityIndicator, 3 StyleSheet, 4 TouchableOpacity, 5 View, 6} from 'react-native' 7import {msg, Trans} from '@lingui/macro' 8import {useLingui} from '@lingui/react' 9 10import {HITSLOP_20} from '#/lib/constants' 11import {atoms as a, useTheme} from '#/alf' 12import {Button} from '#/components/Button' 13import {Fill} from '#/components/Fill' 14import * as Prompt from '#/components/Prompt' 15import {Text} from '#/components/Typography' 16import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' 17 18export function GifPresentationControls({ 19 onPress, 20 isPlaying, 21 isLoading, 22 altText, 23}: { 24 onPress: () => void 25 isPlaying: boolean 26 isLoading?: boolean 27 altText?: string 28}) { 29 const {_} = useLingui() 30 const t = useTheme() 31 32 return ( 33 <> 34 <Button 35 label={isPlaying ? _(msg`Pause GIF`) : _(msg`Play GIF`)} 36 accessibilityHint={_(msg`Plays or pauses the GIF`)} 37 style={[ 38 a.absolute, 39 a.align_center, 40 a.justify_center, 41 a.inset_0, 42 {zIndex: 2}, 43 ]} 44 onPress={onPress}> 45 {isLoading ? ( 46 <View style={[a.align_center, a.justify_center]}> 47 <ActivityIndicator size="large" color="white" /> 48 </View> 49 ) : !isPlaying ? ( 50 <PlayButtonIcon /> 51 ) : ( 52 <></> 53 )} 54 </Button> 55 {!isPlaying && ( 56 <Fill 57 style={[ 58 t.name === 'light' ? t.atoms.bg_contrast_975 : t.atoms.bg, 59 { 60 opacity: 0.2, 61 zIndex: 1, 62 }, 63 ]} 64 /> 65 )} 66 <View style={styles.gifBadgeContainer}> 67 <Text style={[{color: 'white'}, a.font_bold, a.text_xs]}> 68 <Trans>GIF</Trans> 69 </Text> 70 </View> 71 {altText && <AltBadge text={altText} />} 72 </> 73 ) 74} 75 76function AltBadge({text}: {text: string}) { 77 const control = Prompt.usePromptControl() 78 const {_} = useLingui() 79 80 return ( 81 <> 82 <TouchableOpacity 83 testID="altTextButton" 84 accessibilityRole="button" 85 accessibilityLabel={_(msg`Show alt text`)} 86 accessibilityHint="" 87 hitSlop={HITSLOP_20} 88 onPress={control.open} 89 style={styles.altBadgeContainer}> 90 <Text 91 style={[{color: 'white'}, a.font_bold, a.text_xs]} 92 accessible={false}> 93 <Trans>ALT</Trans> 94 </Text> 95 </TouchableOpacity> 96 <Prompt.Outer control={control}> 97 <Prompt.Content> 98 <Prompt.TitleText> 99 <Trans>Alt Text</Trans> 100 </Prompt.TitleText> 101 <Prompt.DescriptionText selectable>{text}</Prompt.DescriptionText> 102 </Prompt.Content> 103 <Prompt.Actions> 104 <Prompt.Action 105 onPress={() => control.close()} 106 cta={_(msg`Close`)} 107 color="secondary" 108 /> 109 </Prompt.Actions> 110 </Prompt.Outer> 111 </> 112 ) 113} 114 115const styles = StyleSheet.create({ 116 gifBadgeContainer: { 117 backgroundColor: 'rgba(0, 0, 0, 0.75)', 118 borderRadius: 6, 119 paddingHorizontal: 4, 120 paddingVertical: 3, 121 position: 'absolute', 122 left: 6, 123 bottom: 6, 124 zIndex: 2, 125 }, 126 altBadgeContainer: { 127 backgroundColor: 'rgba(0, 0, 0, 0.75)', 128 borderRadius: 6, 129 paddingHorizontal: 4, 130 paddingVertical: 3, 131 position: 'absolute', 132 right: 6, 133 bottom: 6, 134 zIndex: 2, 135 }, 136})