diff options
author | dan <dan.abramov@gmail.com> | 2024-11-04 21:31:21 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-04 21:31:21 +0000 |
commit | 26c48373e29643ca7a3248315506131d53d05b8b (patch) | |
tree | 7931136c51cf779cad1a94cce28af78cc7cb0c6e /src/view/com/lightbox/Lightbox.tsx | |
parent | 174988bc5ab00774d200a882312985f55d903d81 (diff) | |
download | voidsky-26c48373e29643ca7a3248315506131d53d05b8b.tar.zst |
Refactor lightbox prop drilling (#6073)
* Refactor lightbox footer to render prop * Unify lightbox types * Unindent * Refactor LightboxFooter props * Move LightboxFooter into the implementation file
Diffstat (limited to 'src/view/com/lightbox/Lightbox.tsx')
-rw-r--r-- | src/view/com/lightbox/Lightbox.tsx | 164 |
1 files changed, 12 insertions, 152 deletions
diff --git a/src/view/com/lightbox/Lightbox.tsx b/src/view/com/lightbox/Lightbox.tsx index 83ea2e941..ed570d5a7 100644 --- a/src/view/com/lightbox/Lightbox.tsx +++ b/src/view/com/lightbox/Lightbox.tsx @@ -1,82 +1,25 @@ import React from 'react' -import {Dimensions, LayoutAnimation, StyleSheet, View} from 'react-native' -import {useSafeAreaInsets} from 'react-native-safe-area-context' import * as MediaLibrary from 'expo-media-library' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {msg, Trans} from '@lingui/macro' +import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {saveImageToMediaLibrary, shareImageModal} from '#/lib/media/manip' -import {colors, s} from '#/lib/styles' -import {isIOS} from '#/platform/detection' import {useLightbox, useLightboxControls} from '#/state/lightbox' -import {ScrollView} from '#/view/com/util/Views' -import {Button} from '../util/forms/Button' -import {Text} from '../util/text/Text' import * as Toast from '../util/Toast' import ImageView from './ImageViewing' -const SCREEN_HEIGHT = Dimensions.get('window').height - export function Lightbox() { const {activeLightbox} = useLightbox() const {closeLightbox} = useLightboxControls() + const onClose = React.useCallback(() => { closeLightbox() }, [closeLightbox]) - if (!activeLightbox) { - return null - } else if (activeLightbox.type === 'profile-image') { - const opts = activeLightbox - return ( - <ImageView - images={[ - { - uri: opts.profile.avatar || '', - thumbUri: opts.profile.avatar || '', - dimensions: { - // It's fine if it's actually smaller but we know it's 1:1. - height: 1000, - width: 1000, - }, - }, - ]} - initialImageIndex={0} - thumbDims={opts.thumbDims} - visible - onRequestClose={onClose} - FooterComponent={LightboxFooter} - /> - ) - } else if (activeLightbox.type === 'images') { - const opts = activeLightbox - return ( - <ImageView - images={opts.images.map(img => ({...img}))} - initialImageIndex={opts.index} - thumbDims={opts.thumbDims} - visible - onRequestClose={onClose} - FooterComponent={LightboxFooter} - /> - ) - } else { - return null - } -} - -function LightboxFooter({imageIndex}: {imageIndex: number}) { const {_} = useLingui() - const {activeLightbox} = useLightbox() - const [isAltExpanded, setAltExpanded] = React.useState(false) const [permissionResponse, requestPermission] = MediaLibrary.usePermissions({ granularPermissions: ['photo'], }) - const insets = useSafeAreaInsets() - const svMaxHeight = SCREEN_HEIGHT - insets.top - 50 - const isMomentumScrolling = React.useRef(false) - const saveImageToAlbumWithToasts = React.useCallback( async (uri: string) => { if (!permissionResponse || permissionResponse.granted === false) { @@ -96,7 +39,6 @@ function LightboxFooter({imageIndex}: {imageIndex: number}) { } return } - try { await saveImageToMediaLibrary({uri}) Toast.show(_(msg`Saved to your camera roll`)) @@ -107,101 +49,19 @@ function LightboxFooter({imageIndex}: {imageIndex: number}) { [permissionResponse, requestPermission, _], ) - const lightbox = activeLightbox - if (!lightbox) { + if (!activeLightbox) { return null } - let altText = '' - let uri = '' - if (lightbox.type === 'images') { - const opts = lightbox - uri = opts.images[imageIndex].uri - altText = opts.images[imageIndex].alt || '' - } else if (lightbox.type === 'profile-image') { - const opts = lightbox - uri = opts.profile.avatar || '' - } - return ( - <ScrollView - style={[ - { - backgroundColor: '#000d', - }, - {maxHeight: svMaxHeight}, - ]} - scrollEnabled={isAltExpanded} - onMomentumScrollBegin={() => { - isMomentumScrolling.current = true - }} - onMomentumScrollEnd={() => { - isMomentumScrolling.current = false - }} - contentContainerStyle={{ - paddingTop: 16, - paddingBottom: insets.bottom + 10, - paddingHorizontal: 24, - }}> - {altText ? ( - <View accessibilityRole="button" style={styles.footerText}> - <Text - style={[s.gray3]} - numberOfLines={isAltExpanded ? undefined : 3} - selectable - onPress={() => { - if (isMomentumScrolling.current) { - return - } - LayoutAnimation.configureNext({ - duration: 450, - update: {type: 'spring', springDamping: 1}, - }) - setAltExpanded(prev => !prev) - }} - onLongPress={() => {}}> - {altText} - </Text> - </View> - ) : null} - <View style={styles.footerBtns}> - <Button - type="primary-outline" - style={styles.footerBtn} - onPress={() => saveImageToAlbumWithToasts(uri)}> - <FontAwesomeIcon icon={['far', 'floppy-disk']} style={s.white} /> - <Text type="xl" style={s.white}> - <Trans context="action">Save</Trans> - </Text> - </Button> - <Button - type="primary-outline" - style={styles.footerBtn} - onPress={() => shareImageModal({uri})}> - <FontAwesomeIcon icon="arrow-up-from-bracket" style={s.white} /> - <Text type="xl" style={s.white}> - <Trans context="action">Share</Trans> - </Text> - </Button> - </View> - </ScrollView> + <ImageView + images={activeLightbox.images} + initialImageIndex={activeLightbox.index} + thumbDims={activeLightbox.thumbDims} + visible + onRequestClose={onClose} + onPressSave={saveImageToAlbumWithToasts} + onPressShare={uri => shareImageModal({uri})} + /> ) } - -const styles = StyleSheet.create({ - footerText: { - paddingBottom: isIOS ? 20 : 16, - }, - footerBtns: { - flexDirection: 'row', - justifyContent: 'center', - gap: 8, - }, - footerBtn: { - flexDirection: 'row', - alignItems: 'center', - gap: 8, - backgroundColor: 'transparent', - borderColor: colors.white, - }, -}) |