diff --git a/package.json b/package.json
index 0fe3e7f6..638bb6c9 100644
--- a/package.json
+++ b/package.json
@@ -126,7 +126,7 @@
"react-native-reanimated": "^3.3.0",
"react-native-root-siblings": "^4.1.1",
"react-native-safe-area-context": "^4.4.1",
- "react-native-screens": "^3.13.1",
+ "react-native-screens": "^3.20.0",
"react-native-splash-screen": "^3.3.0",
"react-native-svg": "13.4.0",
"react-native-url-polyfill": "^1.3.0",
diff --git a/src/view/com/composer/photos/Gallery.tsx b/src/view/com/composer/photos/Gallery.tsx
index f46c0533..c226d25c 100644
--- a/src/view/com/composer/photos/Gallery.tsx
+++ b/src/view/com/composer/photos/Gallery.tsx
@@ -1,16 +1,16 @@
-import React, {useCallback} from 'react'
+import React from 'react'
import {ImageStyle, Keyboard} from 'react-native'
import {GalleryModel} from 'state/models/media/gallery'
import {observer} from 'mobx-react-lite'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {colors} from 'lib/styles'
+import {s, colors} from 'lib/styles'
import {StyleSheet, TouchableOpacity, View} from 'react-native'
-import {ImageModel} from 'state/models/media/image'
import {Image} from 'expo-image'
import {Text} from 'view/com/util/text/Text'
import {isDesktopWeb} from 'platform/detection'
import {openAltTextModal} from 'lib/media/alt-text'
import {useStores} from 'state/index'
+import {usePalette} from 'lib/hooks/usePalette'
interface Props {
gallery: GalleryModel
@@ -18,67 +18,39 @@ interface Props {
export const Gallery = observer(function ({gallery}: Props) {
const store = useStores()
- const getImageStyle = useCallback(() => {
- let side: number
+ const pal = usePalette('default')
- if (gallery.size === 1) {
- side = 250
- } else {
- side = (isDesktopWeb ? 560 : 350) / gallery.size
- }
+ let side: number
- return {
- height: side,
- width: side,
- }
- }, [gallery])
+ if (gallery.size === 1) {
+ side = 250
+ } else {
+ side = (isDesktopWeb ? 560 : 350) / gallery.size
+ }
- const imageStyle = getImageStyle()
- const handleAddImageAltText = useCallback(
- (image: ImageModel) => {
- Keyboard.dismiss()
- openAltTextModal(store, image)
- },
- [store],
- )
- const handleRemovePhoto = useCallback(
- (image: ImageModel) => {
- gallery.remove(image)
- },
- [gallery],
- )
-
- const handleEditPhoto = useCallback(
- (image: ImageModel) => {
- gallery.edit(image)
- },
- [gallery],
- )
+ const imageStyle = {
+ height: side,
+ width: side,
+ }
const isOverflow = !isDesktopWeb && gallery.size > 2
- const imageControlLabelStyle = {
- borderRadius: 5,
- paddingHorizontal: 10,
- position: 'absolute' as const,
- zIndex: 1,
- ...(isOverflow
- ? {
- left: 4,
- bottom: 4,
- }
- : isDesktopWeb && gallery.size < 3
- ? {
- left: 8,
- top: 8,
- }
- : {
- left: 4,
- top: 4,
- }),
- }
+ const altTextControlStyle = isOverflow
+ ? {
+ left: 4,
+ bottom: 4,
+ }
+ : isDesktopWeb && gallery.size < 3
+ ? {
+ left: 8,
+ top: 8,
+ }
+ : {
+ left: 4,
+ top: 4,
+ }
- const imageControlsSubgroupStyle = {
+ const imageControlsStyle = {
display: 'flex' as const,
flexDirection: 'row' as const,
position: 'absolute' as const,
@@ -103,63 +75,90 @@ export const Gallery = observer(function ({gallery}: Props) {
}
return !gallery.isEmpty ? (
-
- {gallery.images.map(image => (
-
- {
- handleAddImageAltText(image)
- }}
- style={imageControlLabelStyle}>
- ALT
-
-
+ <>
+
+ {gallery.images.map(image => (
+
{
- handleEditPhoto(image)
+ Keyboard.dismiss()
+ openAltTextModal(store, image)
}}
- style={styles.imageControl}>
-
+ style={[styles.altTextControl, altTextControlStyle]}>
+ ALT
+ {image.altText.length > 0 ? (
+
+ ) : undefined}
+
+ gallery.edit(image)}
+ style={styles.imageControl}>
+
+
+ gallery.remove(image)}
+ style={styles.imageControl}>
+
+
+
handleRemovePhoto(image)}
- style={styles.imageControl}>
-
-
-
+ onPress={() => {
+ Keyboard.dismiss()
+ openAltTextModal(store, image)
+ }}
+ style={styles.altTextHiddenRegion}
+ />
-
+
+
+ ))}
+
+
+
+
- ))}
-
+
+ Alt text describes images for blind and low-vision users, and helps
+ give context to everyone.
+
+
+ >
) : null
})
@@ -179,19 +178,46 @@ const styles = StyleSheet.create({
height: 24,
borderRadius: 12,
backgroundColor: 'rgba(0, 0, 0, 0.75)',
- borderWidth: 0.5,
alignItems: 'center',
justifyContent: 'center',
},
- imageControlTextContent: {
+ altTextControl: {
+ position: 'absolute',
+ zIndex: 1,
borderRadius: 6,
+ backgroundColor: 'rgba(0, 0, 0, 0.75)',
+ paddingHorizontal: 8,
+ paddingVertical: 3,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ altTextControlLabel: {
color: 'white',
fontSize: 12,
fontWeight: 'bold',
letterSpacing: 1,
- backgroundColor: 'rgba(0, 0, 0, 0.75)',
- borderWidth: 0.5,
- paddingHorizontal: 10,
- paddingVertical: 3,
+ },
+ altTextHiddenRegion: {
+ position: 'absolute',
+ left: 4,
+ right: 4,
+ bottom: 4,
+ top: 30,
+ zIndex: 1,
+ },
+
+ reminder: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 8,
+ borderRadius: 8,
+ paddingVertical: 14,
+ },
+ infoIcon: {
+ width: 22,
+ height: 22,
+ borderRadius: 12,
+ alignItems: 'center',
+ justifyContent: 'center',
},
})
diff --git a/src/view/com/modals/AltImage.tsx b/src/view/com/modals/AltImage.tsx
index 07270d55..e1145a0f 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(() => {
+ 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 (
-
- Add alt text
- setAltText(enforceLen(text, MAX_ALT_TEXT))}
- accessibilityLabel="Image alt text"
- accessibilityHint="Sets image alt text for screenreaders"
- accessibilityLabelledBy="imageAltText"
- />
-
-
-
-
- Save
-
-
-
-
-
-
- Cancel
-
+
+
+
+
+
-
-
-
+ setAltText(enforceLen(text, MAX_ALT_TEXT))}
+ accessibilityLabel="Image alt text"
+ accessibilityHint=""
+ accessibilityLabelledBy="imageAltText"
+ autoFocus
+ />
+
+
+
+
+ Save
+
+
+
+
+
+
+ Cancel
+
+
+
+
+
+
+
)
}
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,
},
- title: {
- textAlign: 'center',
- fontWeight: 'bold',
- fontSize: 24,
+ scrollContainer: {
+ flex: 1,
+ height: '100%',
+ paddingHorizontal: isDesktopWeb ? 0 : 12,
+ },
+ scrollInner: {
+ gap: 12,
+ },
+ imageContainer: {
+ borderRadius: 8,
},
textArea: {
borderWidth: 1,
diff --git a/src/view/com/util/images/Gallery.tsx b/src/view/com/util/images/Gallery.tsx
index 723db289..a7a64b17 100644
--- a/src/view/com/util/images/Gallery.tsx
+++ b/src/view/com/util/images/Gallery.tsx
@@ -45,23 +45,28 @@ export const GalleryItem: FC = ({
accessibilityIgnoresInvertColors
/>
- {image.alt === '' ? null : ALT}
+ {image.alt === '' ? null : (
+
+ ALT
+
+ )}
)
}
const styles = StyleSheet.create({
- alt: {
+ altContainer: {
backgroundColor: 'rgba(0, 0, 0, 0.75)',
borderRadius: 6,
- color: 'white',
- fontSize: 12,
- fontWeight: 'bold',
- letterSpacing: 1,
- paddingHorizontal: 10,
+ paddingHorizontal: 6,
paddingVertical: 3,
position: 'absolute',
left: 6,
bottom: 6,
},
+ alt: {
+ color: 'white',
+ fontSize: 10,
+ fontWeight: 'bold',
+ },
})
diff --git a/src/view/com/util/post-embeds/index.tsx b/src/view/com/util/post-embeds/index.tsx
index 53ef1731..7f2244b7 100644
--- a/src/view/com/util/post-embeds/index.tsx
+++ b/src/view/com/util/post-embeds/index.tsx
@@ -126,7 +126,11 @@ export function PostEmbeds({
onPress={() => openLightbox(0)}
onPressIn={() => onPressIn(0)}
style={styles.singleImage}>
- {alt === '' ? null : ALT}
+ {alt === '' ? null : (
+
+ ALT
+
+ )}
)
@@ -201,17 +205,18 @@ const styles = StyleSheet.create({
borderRadius: 8,
marginTop: 4,
},
- alt: {
+ altContainer: {
backgroundColor: 'rgba(0, 0, 0, 0.75)',
borderRadius: 6,
- color: 'white',
- fontSize: 12,
- fontWeight: 'bold',
- letterSpacing: 1,
- paddingHorizontal: 10,
+ paddingHorizontal: 6,
paddingVertical: 3,
position: 'absolute',
left: 6,
bottom: 6,
},
+ alt: {
+ color: 'white',
+ fontSize: 10,
+ fontWeight: 'bold',
+ },
})
diff --git a/yarn.lock b/yarn.lock
index 63a3ca9c..35357c55 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -15339,10 +15339,10 @@ react-native-safe-area-context@^4.4.1:
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.5.3.tgz#e98eb1a73a6b3846d296545fe74760754dbaaa69"
integrity sha512-ihYeGDEBSkYH+1aWnadNhVtclhppVgd/c0tm4mj0+HV11FoiWJ8N6ocnnZnRLvM5Fxc+hUqxR9bm5AXU3rXiyA==
-react-native-screens@^3.13.1:
- version "3.20.0"
- resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.20.0.tgz#4d154177395e5541387d9a05bc2e12e54d2fb5b1"
- integrity sha512-joWUKWAVHxymP3mL9gYApFHAsbd9L6ZcmpoZa6Sl3W/82bvvNVMqcfP7MeNqVCg73qZ8yL4fW+J/syusHleUgg==
+react-native-screens@^3.20.0:
+ version "3.22.0"
+ resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.22.0.tgz#7d892baf964fddb642b5eec71a09e2aeb501e578"
+ integrity sha512-csLypBSXIt/egh37YJmokETptZJCtZdoZBsZNLR9n31GesDyVogprT+MM22dEPDuxPxt/mFWq+lSpVwk7khuTw==
dependencies:
react-freeze "^1.0.0"
warn-once "^0.1.0"