Skip to content

Commit

Permalink
Port remaining lightbox code to Reanimated (#1669)
Browse files Browse the repository at this point in the history
* Port remaining lightbox code to Reanimated

* Fix  memoization
  • Loading branch information
gaearon authored Oct 10, 2023
1 parent 0b44af3 commit a48c213
Showing 1 changed file with 27 additions and 42 deletions.
69 changes: 27 additions & 42 deletions src/view/com/lightbox/ImageViewing/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
// Original code copied and simplified from the link below as the codebase is currently not maintained:
// https://github.com/jobtoday/react-native-image-viewing

import React, {ComponentType, useMemo, useState} from 'react'
import {Animated, StyleSheet, View, ModalProps, Platform} from 'react-native'
import React, {ComponentType, useCallback, useMemo, useState} from 'react'
import {StyleSheet, View, Platform} from 'react-native'

import ImageItem from './components/ImageItem/ImageItem'
import ImageDefaultHeader from './components/ImageDefaultHeader'

import {ImageSource} from './@types'
import Animated, {useAnimatedStyle, withSpring} from 'react-native-reanimated'
import {Edge, SafeAreaView} from 'react-native-safe-area-context'
import PagerView from 'react-native-pager-view'

Expand All @@ -23,19 +24,12 @@ type Props = {
initialImageIndex: number
visible: boolean
onRequestClose: () => void
presentationStyle?: ModalProps['presentationStyle']
animationType?: ModalProps['animationType']
backgroundColor?: string
HeaderComponent?: ComponentType<{imageIndex: number}>
FooterComponent?: ComponentType<{imageIndex: number}>
}

const DEFAULT_BG_COLOR = '#000'
const INITIAL_POSITION = {x: 0, y: 0}
const ANIMATION_CONFIG = {
duration: 200,
useNativeDriver: true,
}

function ImageViewing({
images,
Expand All @@ -49,37 +43,25 @@ function ImageViewing({
const [isScaled, setIsScaled] = useState(false)
const [isDragging, setIsDragging] = useState(false)
const [imageIndex, setImageIndex] = useState(initialImageIndex)
const [headerTranslate] = useState(
() => new Animated.ValueXY(INITIAL_POSITION),
)
const [footerTranslate] = useState(
() => new Animated.ValueXY(INITIAL_POSITION),
)

const toggleBarsVisible = (isVisible: boolean) => {
if (isVisible) {
Animated.parallel([
Animated.timing(headerTranslate.y, {...ANIMATION_CONFIG, toValue: 0}),
Animated.timing(footerTranslate.y, {...ANIMATION_CONFIG, toValue: 0}),
]).start()
} else {
Animated.parallel([
Animated.timing(headerTranslate.y, {
...ANIMATION_CONFIG,
toValue: -300,
}),
Animated.timing(footerTranslate.y, {
...ANIMATION_CONFIG,
toValue: 300,
}),
]).start()
}
}
const animatedHeaderStyle = useAnimatedStyle(() => ({
transform: [
{
translateY: withClampedSpring(isScaled ? -300 : 0),
},
],
}))
const animatedFooterStyle = useAnimatedStyle(() => ({
transform: [
{
translateY: withClampedSpring(isScaled ? 300 : 0),
},
],
}))

const onZoom = (nextIsScaled: boolean) => {
toggleBarsVisible(!nextIsScaled)
setIsScaled(false)
}
const onZoom = useCallback((nextIsScaled: boolean) => {
setIsScaled(nextIsScaled)
}, [])

const edges = useMemo(() => {
if (Platform.OS === 'android') {
Expand All @@ -92,16 +74,14 @@ function ImageViewing({
return null
}

const headerTransform = headerTranslate.getTranslateTransform()
const footerTransform = footerTranslate.getTranslateTransform()
return (
<SafeAreaView
style={styles.screen}
edges={edges}
aria-modal
accessibilityViewIsModal>
<View style={[styles.container, {backgroundColor}]}>
<Animated.View style={[styles.header, {transform: headerTransform}]}>
<Animated.View style={[styles.header, animatedHeaderStyle]}>
{typeof HeaderComponent !== 'undefined' ? (
React.createElement(HeaderComponent, {
imageIndex,
Expand Down Expand Up @@ -134,7 +114,7 @@ function ImageViewing({
))}
</PagerView>
{typeof FooterComponent !== 'undefined' && (
<Animated.View style={[styles.footer, {transform: footerTransform}]}>
<Animated.View style={[styles.footer, animatedFooterStyle]}>
{React.createElement(FooterComponent, {
imageIndex,
})}
Expand Down Expand Up @@ -179,4 +159,9 @@ const EnhancedImageViewing = (props: Props) => (
<ImageViewing key={props.initialImageIndex} {...props} />
)

function withClampedSpring(value: any) {
'worklet'
return withSpring(value, {overshootClamping: true})
}

export default EnhancedImageViewing

0 comments on commit a48c213

Please sign in to comment.