[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:
parent
4ef853ef6c
commit
d97e75c62f
8 changed files with 127 additions and 179 deletions
|
@ -1,31 +1,75 @@
|
|||
import React from 'react'
|
||||
import {Pressable, StyleSheet, View} from 'react-native'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import ImageView from './ImageViewing'
|
||||
import {useStores} from 'state/index'
|
||||
import * as models from 'state/models/ui/shell'
|
||||
import {saveImageModal} from 'lib/media/manip'
|
||||
import {ImageSource} from './ImageViewing/@types'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {s, colors} from 'lib/styles'
|
||||
import {Button} from '../util/forms/Button'
|
||||
import {isIOS} from 'platform/detection'
|
||||
|
||||
export const Lightbox = observer(function Lightbox() {
|
||||
const store = useStores()
|
||||
if (!store.shell.isLightboxActive) {
|
||||
return null
|
||||
}
|
||||
const [isAltExpanded, setAltExpanded] = React.useState(false)
|
||||
|
||||
const onClose = () => {
|
||||
const onClose = React.useCallback(() => {
|
||||
store.shell.closeLightbox()
|
||||
}
|
||||
const onLongPress = (image: ImageSource) => {
|
||||
if (
|
||||
typeof image === 'object' &&
|
||||
'uri' in image &&
|
||||
typeof image.uri === 'string'
|
||||
) {
|
||||
saveImageModal({uri: image.uri})
|
||||
}
|
||||
}
|
||||
}, [store])
|
||||
|
||||
if (store.shell.activeLightbox?.name === 'profile-image') {
|
||||
const LightboxFooter = React.useCallback(
|
||||
({imageIndex}: {imageIndex: number}) => {
|
||||
const lightbox = store.shell.activeLightbox
|
||||
if (!lightbox) {
|
||||
return null
|
||||
}
|
||||
|
||||
let altText = ''
|
||||
let uri
|
||||
if (lightbox.name === 'images') {
|
||||
const opts = store.shell.activeLightbox as models.ImagesLightbox
|
||||
uri = opts.images[imageIndex].uri
|
||||
altText = opts.images[imageIndex].alt
|
||||
} else if (store.shell.activeLightbox.name === 'profile-image') {
|
||||
const opts = store.shell.activeLightbox as models.ProfileImageLightbox
|
||||
uri = opts.profileView.avatar
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[styles.footer]}>
|
||||
{altText ? (
|
||||
<Pressable
|
||||
onPress={() => setAltExpanded(!isAltExpanded)}
|
||||
accessibilityRole="button">
|
||||
<Text
|
||||
style={[s.gray3, styles.footerText]}
|
||||
numberOfLines={isAltExpanded ? undefined : 3}>
|
||||
{altText}
|
||||
</Text>
|
||||
</Pressable>
|
||||
) : null}
|
||||
<View style={styles.footerBtns}>
|
||||
<Button
|
||||
type="primary-outline"
|
||||
style={styles.footerBtn}
|
||||
onPress={() => saveImageModal({uri})}>
|
||||
<FontAwesomeIcon icon="arrow-up-from-bracket" style={s.white} />
|
||||
<Text type="xl" style={s.white}>
|
||||
Share
|
||||
</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
},
|
||||
[store.shell.activeLightbox, isAltExpanded, setAltExpanded],
|
||||
)
|
||||
|
||||
if (!store.shell.activeLightbox) {
|
||||
return null
|
||||
} else if (store.shell.activeLightbox.name === 'profile-image') {
|
||||
const opts = store.shell.activeLightbox as models.ProfileImageLightbox
|
||||
return (
|
||||
<ImageView
|
||||
|
@ -33,20 +77,44 @@ export const Lightbox = observer(function Lightbox() {
|
|||
imageIndex={0}
|
||||
visible
|
||||
onRequestClose={onClose}
|
||||
FooterComponent={LightboxFooter}
|
||||
/>
|
||||
)
|
||||
} else if (store.shell.activeLightbox?.name === 'images') {
|
||||
} else if (store.shell.activeLightbox.name === 'images') {
|
||||
const opts = store.shell.activeLightbox as models.ImagesLightbox
|
||||
return (
|
||||
<ImageView
|
||||
images={opts.uris.map(uri => ({uri}))}
|
||||
images={opts.images.map(({uri}) => ({uri}))}
|
||||
imageIndex={opts.index}
|
||||
visible
|
||||
onRequestClose={onClose}
|
||||
onLongPress={onLongPress}
|
||||
FooterComponent={LightboxFooter}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
footer: {
|
||||
paddingTop: 16,
|
||||
paddingBottom: isIOS ? 40 : 24,
|
||||
paddingHorizontal: 24,
|
||||
backgroundColor: '#000d',
|
||||
},
|
||||
footerText: {
|
||||
paddingBottom: isIOS ? 20 : 16,
|
||||
},
|
||||
footerBtns: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
footerBtn: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: colors.white,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -10,11 +10,13 @@ import {observer} from 'mobx-react-lite'
|
|||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {useStores} from 'state/index'
|
||||
import * as models from 'state/models/ui/shell'
|
||||
import {colors} from 'lib/styles'
|
||||
import {colors, s} from 'lib/styles'
|
||||
import ImageDefaultHeader from './ImageViewing/components/ImageDefaultHeader'
|
||||
import {Text} from '../util/text/Text'
|
||||
|
||||
interface Img {
|
||||
uri: string
|
||||
alt?: string
|
||||
}
|
||||
|
||||
export const Lightbox = observer(function Lightbox() {
|
||||
|
@ -37,7 +39,7 @@ export const Lightbox = observer(function Lightbox() {
|
|||
}
|
||||
} else if (activeLightbox instanceof models.ImagesLightbox) {
|
||||
const opts = activeLightbox
|
||||
imgs = opts.uris.map(uri => ({uri}))
|
||||
imgs = opts.images
|
||||
}
|
||||
|
||||
if (!imgs) {
|
||||
|
@ -131,6 +133,11 @@ function LightboxInner({
|
|||
)}
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
{imgs[index].alt ? (
|
||||
<View style={styles.footer}>
|
||||
<Text style={s.white}>{imgs[index].alt}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
<View style={styles.closeBtn}>
|
||||
<ImageDefaultHeader onRequestClose={onClose} />
|
||||
</View>
|
||||
|
@ -183,4 +190,9 @@ const styles = StyleSheet.create({
|
|||
right: 30,
|
||||
top: '50%',
|
||||
},
|
||||
footer: {
|
||||
paddingHorizontal: 32,
|
||||
paddingVertical: 24,
|
||||
backgroundColor: colors.black,
|
||||
},
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue