Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Rework alt-text input to use bottom sheet (#2355)

* Rework alt-text input to use bottom sheet

* Add translations

authored by

Paul Frazee and committed by
GitHub
d95972c9 0842df36

+65 -82
+65 -82
src/view/com/modals/AltImage.tsx
··· 1 1 import React, {useMemo, useCallback, useState} from 'react' 2 2 import { 3 3 ImageStyle, 4 - KeyboardAvoidingView, 5 - ScrollView, 6 4 StyleSheet, 7 - TextInput, 8 5 TouchableOpacity, 9 6 View, 10 7 useWindowDimensions, 11 8 } from 'react-native' 9 + import {ScrollView, TextInput} from './util' 12 10 import {Image} from 'expo-image' 13 11 import {usePalette} from 'lib/hooks/usePalette' 14 12 import {gradients, s} from 'lib/styles' ··· 17 15 import {useTheme} from 'lib/ThemeContext' 18 16 import {Text} from '../util/text/Text' 19 17 import LinearGradient from 'react-native-linear-gradient' 20 - import {isAndroid, isWeb} from 'platform/detection' 18 + import {isWeb} from 'platform/detection' 21 19 import {ImageModel} from 'state/models/media/image' 22 20 import {useLingui} from '@lingui/react' 23 21 import {Trans, msg} from '@lingui/macro' 24 22 import {useModalControls} from '#/state/modals' 25 23 26 - export const snapPoints = ['fullscreen'] 24 + export const snapPoints = ['100%'] 27 25 28 26 interface Props { 29 27 image: ImageModel ··· 54 52 } 55 53 }, [image, windim]) 56 54 55 + const onUpdate = useCallback( 56 + (v: string) => { 57 + v = enforceLen(v, MAX_ALT_TEXT) 58 + setAltText(v) 59 + image.setAltText(v) 60 + }, 61 + [setAltText, image], 62 + ) 63 + 57 64 const onPressSave = useCallback(() => { 58 65 image.setAltText(altText) 59 66 closeModal() 60 67 }, [closeModal, image, altText]) 61 68 62 - const onPressCancel = () => { 63 - closeModal() 64 - } 65 - 66 69 return ( 67 - <KeyboardAvoidingView 68 - behavior={isAndroid ? 'height' : 'padding'} 69 - style={[pal.view, styles.container]}> 70 - <ScrollView 71 - testID="altTextImageModal" 72 - style={styles.scrollContainer} 73 - keyboardShouldPersistTaps="always" 74 - nativeID="imageAltText"> 75 - <View style={styles.scrollInner}> 76 - <View style={[pal.viewLight, styles.imageContainer]}> 77 - <Image 78 - testID="selectedPhotoImage" 79 - style={imageStyles} 80 - source={{ 81 - uri: image.cropped?.path ?? image.path, 82 - }} 83 - contentFit="contain" 84 - accessible={true} 85 - accessibilityIgnoresInvertColors 86 - /> 87 - </View> 88 - <TextInput 89 - testID="altTextImageInput" 90 - style={[styles.textArea, pal.border, pal.text]} 91 - keyboardAppearance={theme.colorScheme} 92 - multiline 93 - placeholder="Add alt text" 94 - placeholderTextColor={pal.colors.textLight} 95 - value={altText} 96 - onChangeText={text => setAltText(enforceLen(text, MAX_ALT_TEXT))} 97 - accessibilityLabel={_(msg`Image alt text`)} 70 + <ScrollView 71 + testID="altTextImageModal" 72 + style={[pal.view, styles.scrollContainer]} 73 + keyboardShouldPersistTaps="always" 74 + nativeID="imageAltText"> 75 + <View style={styles.scrollInner}> 76 + <View style={[pal.viewLight, styles.imageContainer]}> 77 + <Image 78 + testID="selectedPhotoImage" 79 + style={imageStyles} 80 + source={{ 81 + uri: image.cropped?.path ?? image.path, 82 + }} 83 + contentFit="contain" 84 + accessible={true} 85 + accessibilityIgnoresInvertColors 86 + /> 87 + </View> 88 + <TextInput 89 + testID="altTextImageInput" 90 + style={[styles.textArea, pal.border, pal.text]} 91 + keyboardAppearance={theme.colorScheme} 92 + multiline 93 + placeholder={_(msg`Add alt text`)} 94 + placeholderTextColor={pal.colors.textLight} 95 + value={altText} 96 + onChangeText={onUpdate} 97 + accessibilityLabel={_(msg`Image alt text`)} 98 + accessibilityHint="" 99 + accessibilityLabelledBy="imageAltText" 100 + autoFocus 101 + /> 102 + <View style={styles.buttonControls}> 103 + <TouchableOpacity 104 + testID="altTextImageSaveBtn" 105 + onPress={onPressSave} 106 + accessibilityLabel={_(msg`Save alt text`)} 98 107 accessibilityHint="" 99 - accessibilityLabelledBy="imageAltText" 100 - autoFocus 101 - /> 102 - <View style={styles.buttonControls}> 103 - <TouchableOpacity 104 - testID="altTextImageSaveBtn" 105 - onPress={onPressSave} 106 - accessibilityLabel={_(msg`Save alt text`)} 107 - accessibilityHint={`Saves alt text, which reads: ${altText}`} 108 - accessibilityRole="button"> 109 - <LinearGradient 110 - colors={[gradients.blueLight.start, gradients.blueLight.end]} 111 - start={{x: 0, y: 0}} 112 - end={{x: 1, y: 1}} 113 - style={[styles.button]}> 114 - <Text type="button-lg" style={[s.white, s.bold]}> 115 - <Trans>Save</Trans> 116 - </Text> 117 - </LinearGradient> 118 - </TouchableOpacity> 119 - <TouchableOpacity 120 - testID="altTextImageCancelBtn" 121 - onPress={onPressCancel} 122 - accessibilityRole="button" 123 - accessibilityLabel={_(msg`Cancel add image alt text`)} 124 - accessibilityHint="" 125 - onAccessibilityEscape={onPressCancel}> 126 - <View style={[styles.button]}> 127 - <Text type="button-lg" style={[pal.textLight]}> 128 - <Trans>Cancel</Trans> 129 - </Text> 130 - </View> 131 - </TouchableOpacity> 132 - </View> 108 + accessibilityRole="button"> 109 + <LinearGradient 110 + colors={[gradients.blueLight.start, gradients.blueLight.end]} 111 + start={{x: 0, y: 0}} 112 + end={{x: 1, y: 1}} 113 + style={[styles.button]}> 114 + <Text type="button-lg" style={[s.white, s.bold]}> 115 + <Trans>Done</Trans> 116 + </Text> 117 + </LinearGradient> 118 + </TouchableOpacity> 133 119 </View> 134 - </ScrollView> 135 - </KeyboardAvoidingView> 120 + </View> 121 + </ScrollView> 136 122 ) 137 123 } 138 124 139 125 const styles = StyleSheet.create({ 140 - container: { 141 - flex: 1, 142 - height: '100%', 143 - width: '100%', 144 - paddingVertical: isWeb ? 0 : 18, 145 - }, 146 126 scrollContainer: { 147 127 flex: 1, 148 128 height: '100%', 149 129 paddingHorizontal: isWeb ? 0 : 12, 130 + paddingVertical: isWeb ? 0 : 24, 150 131 }, 151 132 scrollInner: { 152 133 gap: 12, 134 + paddingTop: isWeb ? 0 : 12, 153 135 }, 154 136 imageContainer: { 155 137 borderRadius: 8, ··· 173 155 }, 174 156 buttonControls: { 175 157 gap: 8, 158 + paddingBottom: isWeb ? 0 : 50, 176 159 }, 177 160 })