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