refactor: remove old image alt dialog
This commit is contained in:
@@ -50,12 +50,6 @@ export interface CropImageModal {
|
||||
onSelect: (img?: RNImage) => void
|
||||
}
|
||||
|
||||
export interface AltTextImageModal {
|
||||
name: 'alt-text-image'
|
||||
image: ComposerImage
|
||||
onChange: (next: ComposerImage) => void
|
||||
}
|
||||
|
||||
export interface DeleteAccountModal {
|
||||
name: 'delete-account'
|
||||
}
|
||||
@@ -151,7 +145,6 @@ export type Modal =
|
||||
| ListAddRemoveUsersModal
|
||||
|
||||
// Posts
|
||||
| AltTextImageModal
|
||||
| CropImageModal
|
||||
| EditImageModal
|
||||
| RepostModal
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
import React, {useCallback, useMemo, useState} from 'react'
|
||||
import {
|
||||
ImageStyle,
|
||||
ScrollView as RNScrollView,
|
||||
StyleSheet,
|
||||
TextInput as RNTextInput,
|
||||
TouchableOpacity,
|
||||
useWindowDimensions,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {ComposerImage} from '#/state/gallery'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {MAX_ALT_TEXT} from 'lib/constants'
|
||||
import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {enforceLen} from 'lib/strings/helpers'
|
||||
import {gradients, s} from 'lib/styles'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {ScrollView, TextInput} from './util'
|
||||
|
||||
export const snapPoints = ['100%']
|
||||
|
||||
interface Props {
|
||||
image: ComposerImage
|
||||
onChange: (next: ComposerImage) => void
|
||||
}
|
||||
|
||||
export function Component({image, onChange}: Props) {
|
||||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const {_} = useLingui()
|
||||
const [altText, setAltText] = useState(image.alt)
|
||||
const windim = useWindowDimensions()
|
||||
const {closeModal} = useModalControls()
|
||||
const inputRef = React.useRef<RNTextInput>(null)
|
||||
const scrollViewRef = React.useRef<RNScrollView>(null)
|
||||
const keyboardShown = useIsKeyboardVisible()
|
||||
|
||||
// Autofocus hack when we open the modal. We have to wait for the animation to complete first
|
||||
React.useEffect(() => {
|
||||
setTimeout(() => {
|
||||
inputRef.current?.focus()
|
||||
}, 500)
|
||||
}, [])
|
||||
|
||||
// We'd rather be at the bottom here so that we can easily dismiss the modal instead of having to scroll
|
||||
// (especially on android, it acts weird)
|
||||
React.useEffect(() => {
|
||||
if (keyboardShown[0]) {
|
||||
scrollViewRef.current?.scrollToEnd()
|
||||
}
|
||||
}, [keyboardShown])
|
||||
|
||||
const imageStyles = useMemo<ImageStyle>(() => {
|
||||
const maxWidth = isWeb ? 450 : windim.width
|
||||
const source = image.transformed ?? image.source
|
||||
|
||||
if (source.height > source.width) {
|
||||
return {
|
||||
resizeMode: 'contain',
|
||||
width: '100%',
|
||||
aspectRatio: 1,
|
||||
borderRadius: 8,
|
||||
}
|
||||
}
|
||||
return {
|
||||
width: '100%',
|
||||
height: (maxWidth / source.width) * source.height,
|
||||
borderRadius: 8,
|
||||
}
|
||||
}, [image, windim])
|
||||
|
||||
const onUpdate = useCallback(
|
||||
(v: string) => {
|
||||
v = enforceLen(v, MAX_ALT_TEXT)
|
||||
setAltText(v)
|
||||
},
|
||||
[setAltText],
|
||||
)
|
||||
|
||||
const onPressSave = useCallback(() => {
|
||||
closeModal()
|
||||
onChange({...image, alt: altText.trim()})
|
||||
}, [closeModal, image, altText, onChange])
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
testID="altTextImageModal"
|
||||
style={[pal.view, styles.scrollContainer]}
|
||||
keyboardShouldPersistTaps="always"
|
||||
ref={scrollViewRef}
|
||||
nativeID="imageAltText">
|
||||
<View style={styles.scrollInner}>
|
||||
<View style={[pal.viewLight, styles.imageContainer]}>
|
||||
<Image
|
||||
testID="selectedPhotoImage"
|
||||
style={imageStyles}
|
||||
source={{
|
||||
uri: (image.transformed ?? image.source).path,
|
||||
}}
|
||||
contentFit="contain"
|
||||
accessible={true}
|
||||
accessibilityIgnoresInvertColors
|
||||
enableLiveTextInteraction
|
||||
/>
|
||||
</View>
|
||||
<TextInput
|
||||
testID="altTextImageInput"
|
||||
style={[styles.textArea, pal.border, pal.text]}
|
||||
keyboardAppearance={theme.colorScheme}
|
||||
multiline
|
||||
placeholder={_(msg`Add alt text`)}
|
||||
placeholderTextColor={pal.colors.textLight}
|
||||
value={altText}
|
||||
onChangeText={onUpdate}
|
||||
accessibilityLabel={_(msg`Image alt text`)}
|
||||
accessibilityHint=""
|
||||
accessibilityLabelledBy="imageAltText"
|
||||
// @ts-ignore This is fine, type is weird on the BottomSheetTextInput
|
||||
ref={inputRef}
|
||||
/>
|
||||
<View style={styles.buttonControls}>
|
||||
<TouchableOpacity
|
||||
testID="altTextImageSaveBtn"
|
||||
onPress={onPressSave}
|
||||
accessibilityLabel={_(msg`Save alt text`)}
|
||||
accessibilityHint=""
|
||||
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]}>
|
||||
<Trans>Done</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
scrollContainer: {
|
||||
flex: 1,
|
||||
height: '100%',
|
||||
paddingHorizontal: isWeb ? 0 : 12,
|
||||
paddingVertical: isWeb ? 0 : 24,
|
||||
},
|
||||
scrollInner: {
|
||||
gap: 12,
|
||||
paddingTop: isWeb ? 0 : 12,
|
||||
},
|
||||
imageContainer: {
|
||||
borderRadius: 8,
|
||||
},
|
||||
textArea: {
|
||||
borderWidth: 1,
|
||||
borderRadius: 6,
|
||||
paddingTop: 10,
|
||||
paddingHorizontal: 12,
|
||||
fontSize: 16,
|
||||
height: 100,
|
||||
textAlignVertical: 'top',
|
||||
},
|
||||
button: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: '100%',
|
||||
borderRadius: 32,
|
||||
padding: 10,
|
||||
},
|
||||
buttonControls: {
|
||||
gap: 8,
|
||||
paddingBottom: isWeb ? 0 : 50,
|
||||
},
|
||||
})
|
||||
@@ -7,8 +7,6 @@ import {useModalControls, useModals} from '#/state/modals'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {createCustomBackdrop} from '../util/BottomSheetCustomBackdrop'
|
||||
import * as AddAppPassword from './AddAppPasswords'
|
||||
import * as AltImageModal from './AltImage'
|
||||
import * as EditImageModal from './AltImage'
|
||||
import * as ChangeEmailModal from './ChangeEmail'
|
||||
import * as ChangeHandleModal from './ChangeHandle'
|
||||
import * as ChangePasswordModal from './ChangePassword'
|
||||
@@ -82,12 +80,6 @@ export function ModalsContainer() {
|
||||
} else if (activeModal?.name === 'threadgate') {
|
||||
snapPoints = ThreadgateModal.snapPoints
|
||||
element = <ThreadgateModal.Component {...activeModal} />
|
||||
} else if (activeModal?.name === 'alt-text-image') {
|
||||
snapPoints = AltImageModal.snapPoints
|
||||
element = <AltImageModal.Component {...activeModal} />
|
||||
} else if (activeModal?.name === 'edit-image') {
|
||||
snapPoints = AltImageModal.snapPoints
|
||||
element = <EditImageModal.Component {...activeModal} />
|
||||
} else if (activeModal?.name === 'change-handle') {
|
||||
snapPoints = ChangeHandleModal.snapPoints
|
||||
element = <ChangeHandleModal.Component {...activeModal} />
|
||||
|
||||
@@ -8,7 +8,6 @@ import {useModalControls, useModals} from '#/state/modals'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import * as AddAppPassword from './AddAppPasswords'
|
||||
import * as AltTextImageModal from './AltImage'
|
||||
import * as ChangeEmailModal from './ChangeEmail'
|
||||
import * as ChangeHandleModal from './ChangeHandle'
|
||||
import * as ChangePasswordModal from './ChangePassword'
|
||||
@@ -56,11 +55,7 @@ function Modal({modal}: {modal: ModalIface}) {
|
||||
}
|
||||
|
||||
const onPressMask = () => {
|
||||
if (
|
||||
modal.name === 'crop-image' ||
|
||||
modal.name === 'edit-image' ||
|
||||
modal.name === 'alt-text-image'
|
||||
) {
|
||||
if (modal.name === 'crop-image' || modal.name === 'edit-image') {
|
||||
return // dont close on mask presses during crop
|
||||
}
|
||||
closeModal()
|
||||
@@ -99,9 +94,8 @@ function Modal({modal}: {modal: ModalIface}) {
|
||||
element = <ContentLanguagesSettingsModal.Component />
|
||||
} else if (modal.name === 'post-languages-settings') {
|
||||
element = <PostLanguagesSettingsModal.Component />
|
||||
} else if (modal.name === 'alt-text-image') {
|
||||
element = <AltTextImageModal.Component {...modal} />
|
||||
} else if (modal.name === 'edit-image') {
|
||||
// @ts-expect-error: todo
|
||||
element = <EditImageModal.Component {...modal} />
|
||||
} else if (modal.name === 'verify-email') {
|
||||
element = <VerifyEmailModal.Component {...modal} />
|
||||
|
||||
Reference in New Issue
Block a user