Bluesky app fork with some witchin' additions 💫

align alt text behaviour between gif types (#9822)

authored by samuel.fm and committed by

GitHub e6c4a539 965b17ff

+63 -75
+3 -74
src/components/Post/Embed/ExternalEmbed/Gif.tsx
··· 1 1 import {useRef, useState} from 'react' 2 - import { 3 - type StyleProp, 4 - StyleSheet, 5 - TouchableOpacity, 6 - View, 7 - type ViewStyle, 8 - } from 'react-native' 9 - import {msg, Trans} from '@lingui/macro' 2 + import {type StyleProp, View, type ViewStyle} from 'react-native' 3 + import {msg} from '@lingui/macro' 10 4 import {useLingui} from '@lingui/react' 11 5 12 - import {HITSLOP_20} from '#/lib/constants' 13 6 import {clamp} from '#/lib/numbers' 14 7 import {type EmbedPlayerParams} from '#/lib/strings/embed-player' 15 8 import {useAutoplayDisabled} from '#/state/preferences' 16 - import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' 17 9 import {atoms as a, useTheme} from '#/alf' 18 10 import {Fill} from '#/components/Fill' 19 11 import {MediaInsetBorder} from '#/components/MediaInsetBorder' 20 - import * as Prompt from '#/components/Prompt' 21 - import {Text} from '#/components/Typography' 22 - import {IS_WEB} from '#/env' 23 12 import {GifView} from '../../../../../modules/expo-bluesky-gif-view' 24 13 import {type GifViewStateChangeEvent} from '../../../../../modules/expo-bluesky-gif-view/src/GifView.types' 25 14 import {GifPresentationControls} from '../VideoEmbed/GifPresentationControls' ··· 94 83 onPress={onPress} 95 84 isPlaying={playerState.isPlaying} 96 85 isLoading={!playerState.isLoaded} 86 + altText={!hideAlt && isPreferredAltText ? altText : undefined} 97 87 /> 98 88 <GifView 99 89 source={params.playerUri} ··· 115 105 ]} 116 106 /> 117 107 )} 118 - {!hideAlt && isPreferredAltText && <AltText text={altText} />} 119 108 </View> 120 109 </View> 121 110 ) 122 111 } 123 - 124 - function AltText({text}: {text: string}) { 125 - const control = Prompt.usePromptControl() 126 - const largeAltBadge = useLargeAltBadgeEnabled() 127 - 128 - const {_} = useLingui() 129 - return ( 130 - <> 131 - <TouchableOpacity 132 - testID="altTextButton" 133 - accessibilityRole="button" 134 - accessibilityLabel={_(msg`Show alt text`)} 135 - accessibilityHint="" 136 - hitSlop={HITSLOP_20} 137 - onPress={control.open} 138 - style={styles.altContainer}> 139 - <Text 140 - style={[styles.alt, largeAltBadge && a.text_xs]} 141 - accessible={false}> 142 - <Trans>ALT</Trans> 143 - </Text> 144 - </TouchableOpacity> 145 - <Prompt.Outer control={control}> 146 - <Prompt.Content> 147 - <Prompt.TitleText> 148 - <Trans>Alt Text</Trans> 149 - </Prompt.TitleText> 150 - <Prompt.DescriptionText selectable>{text}</Prompt.DescriptionText> 151 - </Prompt.Content> 152 - <Prompt.Actions> 153 - <Prompt.Action 154 - onPress={() => control.close()} 155 - cta={_(msg`Close`)} 156 - color="secondary" 157 - /> 158 - </Prompt.Actions> 159 - </Prompt.Outer> 160 - </> 161 - ) 162 - } 163 - 164 - const styles = StyleSheet.create({ 165 - altContainer: { 166 - backgroundColor: 'rgba(0, 0, 0, 0.75)', 167 - borderRadius: 6, 168 - paddingHorizontal: IS_WEB ? 8 : 6, 169 - paddingVertical: IS_WEB ? 6 : 3, 170 - position: 'absolute', 171 - // Related to margin/gap hack. This keeps the alt label in the same position 172 - // on all platforms 173 - right: IS_WEB ? 8 : 5, 174 - bottom: IS_WEB ? 8 : 5, 175 - zIndex: 2, 176 - }, 177 - alt: { 178 - color: 'white', 179 - fontSize: IS_WEB ? 10 : 7, 180 - fontWeight: '600', 181 - }, 182 - })
+55 -1
src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx
··· 1 - import {Pressable, StyleSheet, View} from 'react-native' 1 + import {Pressable, StyleSheet, TouchableOpacity, View} from 'react-native' 2 2 import {msg, Trans} from '@lingui/macro' 3 3 import {useLingui} from '@lingui/react' 4 4 5 + import {HITSLOP_20} from '#/lib/constants' 5 6 import {atoms as a, useTheme} from '#/alf' 6 7 import {Fill} from '#/components/Fill' 7 8 import {Loader} from '#/components/Loader' 9 + import * as Prompt from '#/components/Prompt' 8 10 import {Text} from '#/components/Typography' 9 11 import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' 10 12 ··· 12 14 onPress, 13 15 isPlaying, 14 16 isLoading, 17 + altText, 15 18 }: { 16 19 onPress: () => void 17 20 isPlaying: boolean 18 21 isLoading?: boolean 22 + altText?: string 19 23 }) { 20 24 const {_} = useLingui() 21 25 const t = useTheme() ··· 60 64 <Trans>GIF</Trans> 61 65 </Text> 62 66 </View> 67 + {altText && <AltBadge text={altText} />} 68 + </> 69 + ) 70 + } 71 + 72 + function AltBadge({text}: {text: string}) { 73 + const control = Prompt.usePromptControl() 74 + const {_} = useLingui() 75 + 76 + return ( 77 + <> 78 + <TouchableOpacity 79 + testID="altTextButton" 80 + accessibilityRole="button" 81 + accessibilityLabel={_(msg`Show alt text`)} 82 + accessibilityHint="" 83 + hitSlop={HITSLOP_20} 84 + onPress={control.open} 85 + style={styles.altBadgeContainer}> 86 + <Text 87 + style={[{color: 'white'}, a.font_bold, a.text_xs]} 88 + accessible={false}> 89 + <Trans>ALT</Trans> 90 + </Text> 91 + </TouchableOpacity> 92 + <Prompt.Outer control={control}> 93 + <Prompt.Content> 94 + <Prompt.TitleText> 95 + <Trans>Alt Text</Trans> 96 + </Prompt.TitleText> 97 + <Prompt.DescriptionText selectable>{text}</Prompt.DescriptionText> 98 + </Prompt.Content> 99 + <Prompt.Actions> 100 + <Prompt.Action 101 + onPress={() => control.close()} 102 + cta={_(msg`Close`)} 103 + color="secondary" 104 + /> 105 + </Prompt.Actions> 106 + </Prompt.Outer> 63 107 </> 64 108 ) 65 109 } ··· 72 116 paddingVertical: 3, 73 117 position: 'absolute', 74 118 left: 6, 119 + bottom: 6, 120 + zIndex: 2, 121 + }, 122 + altBadgeContainer: { 123 + backgroundColor: 'rgba(0, 0, 0, 0.75)', 124 + borderRadius: 6, 125 + paddingHorizontal: 4, 126 + paddingVertical: 3, 127 + position: 'absolute', 128 + right: 6, 75 129 bottom: 6, 76 130 zIndex: 2, 77 131 },
+1
src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx
··· 92 92 }} 93 93 isPlaying={isPlaying} 94 94 isLoading={false} 95 + altText={embed.alt} 95 96 /> 96 97 ) : ( 97 98 <VideoPresentationControls
+1
src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx
··· 101 101 fullscreenRef={containerRef} 102 102 hasSubtitleTrack={hasSubtitleTrack} 103 103 isGif={embed.presentation === 'gif'} 104 + altText={embed.alt} 104 105 /> 105 106 </div> 106 107 </View>
+3
src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx
··· 46 46 hlsLoading, 47 47 hasSubtitleTrack, 48 48 isGif, 49 + altText, 49 50 }: { 50 51 videoRef: React.RefObject<HTMLVideoElement | null> 51 52 hlsRef: React.RefObject<Hls | undefined | null> ··· 58 59 hlsLoading: boolean 59 60 hasSubtitleTrack: boolean 60 61 isGif: boolean 62 + altText?: string 61 63 }) { 62 64 const { 63 65 play, ··· 296 298 isPlaying={playing} 297 299 isLoading={showSpinner} 298 300 onPress={onPressPlayPause} 301 + altText={altText} 299 302 /> 300 303 ) 301 304 }