[APP-539] Rework lightbox and alt-image behaviors (#573)

* Replace the long press on the lightbox with footer controls

* Remove long-press from images in the feed

* Tune the lightbox footer control ui

* Replace the AltImageRead modal with the ability to view all alt text in the lightbox footer

* Tune lightbox footer for iOS

* Add alt text to the web lightbox

* Fix lint

* a11y slight changes

---------

Co-authored-by: renahlee <renahlee@outlook.com>
This commit is contained in:
Paul Frazee 2023-05-04 00:54:35 -05:00 committed by GitHub
parent 4ef853ef6c
commit d97e75c62f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 127 additions and 179 deletions

View file

@ -1,8 +1,7 @@
import {AppBskyEmbedImages} from '@atproto/api'
import React, {ComponentProps, FC, useCallback} from 'react'
import {Pressable, StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import React, {ComponentProps, FC} from 'react'
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import {Image} from 'expo-image'
import {useStores} from 'state/index'
type EventFunction = (index: number) => void
@ -26,22 +25,14 @@ export const GalleryItem: FC<GalleryItemProps> = ({
onLongPress,
}) => {
const image = images[index]
const store = useStores()
const onPressAltText = useCallback(() => {
store.shell.openModal({
name: 'alt-text-image-read',
altText: image.alt,
})
}, [image.alt, store.shell])
return (
<View>
<TouchableOpacity
delayPressIn={DELAY_PRESS_IN}
onPress={() => onPress?.(index)}
onPressIn={() => onPressIn?.(index)}
onLongPress={() => onLongPress?.(index)}
onPress={onPress ? () => onPress(index) : undefined}
onPressIn={onPressIn ? () => onPressIn(index) : undefined}
onLongPress={onLongPress ? () => onLongPress(index) : undefined}
accessibilityRole="button"
accessibilityLabel="View image"
accessibilityHint="">
@ -54,15 +45,7 @@ export const GalleryItem: FC<GalleryItemProps> = ({
accessibilityIgnoresInvertColors
/>
</TouchableOpacity>
{image.alt === '' ? null : (
<Pressable
onPress={onPressAltText}
accessibilityRole="button"
accessibilityLabel="View alt text"
accessibilityHint="Opens modal with alt text">
<Text style={styles.alt}>ALT</Text>
</Pressable>
)}
{image.alt === '' ? null : <Text style={styles.alt}>ALT</Text>}
</View>
)
}
@ -78,8 +61,8 @@ const styles = StyleSheet.create({
paddingHorizontal: 10,
paddingVertical: 3,
position: 'absolute',
left: 10,
top: -26,
left: 6,
bottom: 6,
width: 46,
},
})

View file

@ -1,11 +1,10 @@
import React, {useCallback} from 'react'
import React from 'react'
import {
StyleSheet,
StyleProp,
View,
ViewStyle,
Image as RNImage,
Pressable,
Text,
} from 'react-native'
import {
@ -20,7 +19,6 @@ import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
import {ImagesLightbox} from 'state/models/ui/shell'
import {useStores} from 'state/index'
import {usePalette} from 'lib/hooks/usePalette'
import {saveImageModal} from 'lib/media/manip'
import {YoutubeEmbed} from './YoutubeEmbed'
import {ExternalLinkEmbed} from './ExternalLinkEmbed'
import {getYoutubeVideoId} from 'lib/strings/url-helpers'
@ -44,16 +42,6 @@ export function PostEmbeds({
const pal = usePalette('default')
const store = useStores()
const onPressAltText = useCallback(
(alt: string) => {
store.shell.openModal({
name: 'alt-text-image-read',
altText: alt,
})
},
[store.shell],
)
if (
AppBskyEmbedRecordWithMedia.isView(embed) &&
AppBskyEmbedRecord.isViewRecord(embed.record.record) &&
@ -103,20 +91,17 @@ export function PostEmbeds({
const {images} = embed
if (images.length > 0) {
const uris = embed.images.map(img => img.fullsize)
const items = embed.images.map(img => ({uri: img.fullsize, alt: img.alt}))
const openLightbox = (index: number) => {
store.shell.openLightbox(new ImagesLightbox(uris, index))
}
const onLongPress = (index: number) => {
saveImageModal({uri: uris[index]})
store.shell.openLightbox(new ImagesLightbox(items, index))
}
const onPressIn = (index: number) => {
const firstImageToShow = uris[index]
const firstImageToShow = items[index].uri
RNImage.prefetch(firstImageToShow)
uris.forEach(uri => {
if (firstImageToShow !== uri) {
items.forEach(item => {
if (firstImageToShow !== item.uri) {
// First image already prefeched above
RNImage.prefetch(uri)
RNImage.prefetch(item.uri)
}
})
}
@ -129,20 +114,9 @@ export function PostEmbeds({
alt={alt}
uri={thumb}
onPress={() => openLightbox(0)}
onLongPress={() => onLongPress(0)}
onPressIn={() => onPressIn(0)}
style={styles.singleImage}>
{alt === '' ? null : (
<Pressable
onPress={() => {
onPressAltText(alt)
}}
accessibilityRole="button"
accessibilityLabel="View alt text"
accessibilityHint="Opens modal with alt text">
<Text style={styles.alt}>ALT</Text>
</Pressable>
)}
{alt === '' ? null : <Text style={styles.alt}>ALT</Text>}
</AutoSizedImage>
</View>
)
@ -153,7 +127,6 @@ export function PostEmbeds({
<ImageLayoutGrid
images={embed.images}
onPress={openLightbox}
onLongPress={onLongPress}
onPressIn={onPressIn}
style={embed.images.length === 1 ? styles.singleImage : undefined}
/>
@ -209,8 +182,8 @@ const styles = StyleSheet.create({
paddingHorizontal: 10,
paddingVertical: 3,
position: 'absolute',
left: 10,
top: -26,
left: 6,
bottom: 6,
width: 46,
},
})