Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions src/components/themed/QrCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from 'react-native'
import Animated, {
useAnimatedStyle,
useDerivedValue,
useSharedValue,
withTiming
} from 'react-native-reanimated'
import Svg, { Path } from 'react-native-svg'
Expand Down Expand Up @@ -42,6 +42,8 @@ export const QrCode: React.FC<Props> = props => {
// Scale the surface to match the container's size:
const [size, setSize] = React.useState<number>(0)

const layoutPending = size <= 0 || data == null // loading state includes layout timing to avoid flicker

const handleLayout = (event: LayoutChangeEvent): void => {
setSize(event.nativeEvent.layout.height)
}
Expand All @@ -54,9 +56,14 @@ export const QrCode: React.FC<Props> = props => {
const path = svg.replace(/.*d="([^"]*)".*/, '$1')

// Handle animation:
const derivedData = useDerivedValue(() => data)
const opacity = useSharedValue(0)

React.useEffect(() => {
opacity.value = withTiming(data != null ? 1 : 0)
}, [data, opacity])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Fade animation completes before QR code view renders

The opacity animation triggers on data changes, but the Animated.View only renders when layoutPending is false (requiring both size > 0 and data != null). If data is set before layout completes, the animation runs while the ActivityIndicator is still showing, completing before the QR code view mounts. This causes the QR code to pop in without the intended fade effect, since the animation dependency array doesn't include size or layoutPending.

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Fade animation completes before QR code view renders

The opacity animation triggers on data changes, but the Animated.View only renders when layoutPending is false (requiring both size > 0 and data != null). If data is set before layout completes, the animation runs while the ActivityIndicator is still showing, completing before the QR code view mounts. This causes the QR code to pop in without the intended fade effect, since the animation dependency array doesn't include size or layoutPending.

Fix in Cursor Fix in Web


const fadeStyle = useAnimatedStyle(() => ({
opacity: withTiming(derivedData.value != null ? 1 : 0)
opacity: opacity.value
}))

// Create a drawing transform to scale QR cells to device pixels:
Expand Down Expand Up @@ -93,17 +100,18 @@ export const QrCode: React.FC<Props> = props => {
return (
<EdgeTouchableWithoutFeedback onPress={onPress}>
<View style={[styles.container, margin]} onLayout={handleLayout}>
<ActivityIndicator color={theme.iconTappable} />
<Animated.View style={[styles.whiteBox, fadeStyle]}>
{size <= 0 ? null : (
{layoutPending ? (
<ActivityIndicator color={theme.iconTappable} />
) : (
<Animated.View style={[styles.whiteBox, fadeStyle]}>
<View style={styles.whiteBoxInner}>
<Svg height="100%" width="100%" viewBox={viewBox}>
<Path d={path} fill={theme.qrForegroundColor} />
</Svg>
</View>
)}
{icon}
</Animated.View>
{icon}
</Animated.View>
)}
</View>
</EdgeTouchableWithoutFeedback>
)
Expand Down
Loading