diff options
Diffstat (limited to 'src/view/com/modals/AltImage.tsx')
-rw-r--r-- | src/view/com/modals/AltImage.tsx | 167 |
1 files changed, 110 insertions, 57 deletions
diff --git a/src/view/com/modals/AltImage.tsx b/src/view/com/modals/AltImage.tsx index 07270d557..e1145a0fe 100644 --- a/src/view/com/modals/AltImage.tsx +++ b/src/view/com/modals/AltImage.tsx @@ -1,5 +1,15 @@ -import React, {useCallback, useState} from 'react' -import {StyleSheet, TextInput, TouchableOpacity, View} from 'react-native' +import React, {useMemo, useCallback, useState} from 'react' +import { + ImageStyle, + KeyboardAvoidingView, + ScrollView, + StyleSheet, + TextInput, + TouchableOpacity, + View, + useWindowDimensions, +} from 'react-native' +import {Image} from 'expo-image' import {usePalette} from 'lib/hooks/usePalette' import {gradients, s} from 'lib/styles' import {enforceLen} from 'lib/strings/helpers' @@ -8,7 +18,7 @@ import {useTheme} from 'lib/ThemeContext' import {Text} from '../util/text/Text' import LinearGradient from 'react-native-linear-gradient' import {useStores} from 'state/index' -import {isDesktopWeb} from 'platform/detection' +import {isDesktopWeb, isAndroid} from 'platform/detection' import {ImageModel} from 'state/models/media/image' export const snapPoints = ['fullscreen'] @@ -22,6 +32,24 @@ export function Component({image}: Props) { const store = useStores() const theme = useTheme() const [altText, setAltText] = useState(image.altText) + const windim = useWindowDimensions() + + const imageStyles = useMemo<ImageStyle>(() => { + const maxWidth = isDesktopWeb ? 450 : windim.width + if (image.height > image.width) { + return { + resizeMode: 'contain', + width: '100%', + aspectRatio: 1, + borderRadius: 8, + } + } + return { + width: '100%', + height: (maxWidth / image.width) * image.height, + borderRadius: 8, + } + }, [image, windim]) const onPressSave = useCallback(() => { image.setAltText(altText) @@ -33,69 +61,94 @@ export function Component({image}: Props) { } return ( - <View - testID="altTextImageModal" - style={[pal.view, styles.container, s.flex1]} - nativeID="imageAltText"> - <Text style={[styles.title, pal.text]}>Add alt text</Text> - <TextInput - testID="altTextImageInput" - style={[styles.textArea, pal.border, pal.text]} - keyboardAppearance={theme.colorScheme} - multiline - value={altText} - onChangeText={text => setAltText(enforceLen(text, MAX_ALT_TEXT))} - accessibilityLabel="Image alt text" - accessibilityHint="Sets image alt text for screenreaders" - accessibilityLabelledBy="imageAltText" - /> - <View style={styles.buttonControls}> - <TouchableOpacity - testID="altTextImageSaveBtn" - onPress={onPressSave} - accessibilityLabel="Save alt text" - accessibilityHint={`Saves alt text, which reads: ${altText}`} - accessibilityRole="button"> - <LinearGradient - colors={[gradients.blueLight.start, gradients.blueLight.end]} - start={{x: 0, y: 0}} - end={{x: 1, y: 1}} - style={[styles.button]}> - <Text type="button-lg" style={[s.white, s.bold]}> - Save - </Text> - </LinearGradient> - </TouchableOpacity> - <TouchableOpacity - testID="altTextImageCancelBtn" - onPress={onPressCancel} - accessibilityRole="button" - accessibilityLabel="Cancel add image alt text" - accessibilityHint="Exits adding alt text to image" - onAccessibilityEscape={onPressCancel}> - <View style={[styles.button]}> - <Text type="button-lg" style={[pal.textLight]}> - Cancel - </Text> + <KeyboardAvoidingView + behavior={isAndroid ? 'height' : 'padding'} + style={[pal.view, styles.container]}> + <ScrollView + testID="altTextImageModal" + style={styles.scrollContainer} + keyboardShouldPersistTaps="always" + nativeID="imageAltText"> + <View style={styles.scrollInner}> + <View style={[pal.viewLight, styles.imageContainer]}> + <Image + testID="selectedPhotoImage" + style={imageStyles} + source={{ + uri: image.cropped?.path ?? image.path, + }} + accessible={true} + accessibilityIgnoresInvertColors + /> + </View> + <TextInput + testID="altTextImageInput" + style={[styles.textArea, pal.border, pal.text]} + keyboardAppearance={theme.colorScheme} + multiline + placeholder="Add alt text" + placeholderTextColor={pal.colors.textLight} + value={altText} + onChangeText={text => setAltText(enforceLen(text, MAX_ALT_TEXT))} + accessibilityLabel="Image alt text" + accessibilityHint="" + accessibilityLabelledBy="imageAltText" + autoFocus + /> + <View style={styles.buttonControls}> + <TouchableOpacity + testID="altTextImageSaveBtn" + onPress={onPressSave} + accessibilityLabel="Save alt text" + accessibilityHint={`Saves alt text, which reads: ${altText}`} + accessibilityRole="button"> + <LinearGradient + colors={[gradients.blueLight.start, gradients.blueLight.end]} + start={{x: 0, y: 0}} + end={{x: 1, y: 1}} + style={[styles.button]}> + <Text type="button-lg" style={[s.white, s.bold]}> + Save + </Text> + </LinearGradient> + </TouchableOpacity> + <TouchableOpacity + testID="altTextImageCancelBtn" + onPress={onPressCancel} + accessibilityRole="button" + accessibilityLabel="Cancel add image alt text" + accessibilityHint="" + onAccessibilityEscape={onPressCancel}> + <View style={[styles.button]}> + <Text type="button-lg" style={[pal.textLight]}> + Cancel + </Text> + </View> + </TouchableOpacity> </View> - </TouchableOpacity> - </View> - </View> + </View> + </ScrollView> + </KeyboardAvoidingView> ) } const styles = StyleSheet.create({ container: { - gap: 18, - paddingVertical: isDesktopWeb ? 0 : 18, - paddingHorizontal: isDesktopWeb ? 0 : 12, + flex: 1, height: '100%', width: '100%', + paddingVertical: isDesktopWeb ? 0 : 18, + }, + scrollContainer: { + flex: 1, + height: '100%', + paddingHorizontal: isDesktopWeb ? 0 : 12, + }, + scrollInner: { + gap: 12, }, - title: { - textAlign: 'center', - fontWeight: 'bold', - fontSize: 24, + imageContainer: { + borderRadius: 8, }, textArea: { borderWidth: 1, |