Skip to content

Commit

Permalink
Merge pull request #53321 from software-mansion-labs/migrate/textinpu…
Browse files Browse the repository at this point in the history
…t_growlnotification_attachmentmodal_animte_to_reanimate

Migrate/textinput growlnotification attachmentmodal animte to reanimate
  • Loading branch information
mountiny authored Dec 9, 2024
2 parents 59193c6 + a4d1f67 commit 034b2d9
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 68 deletions.
12 changes: 6 additions & 6 deletions src/components/AttachmentModal.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import {Str} from 'expensify-common';
import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {Animated, Keyboard, View} from 'react-native';
import {Keyboard, View} from 'react-native';
import {GestureHandlerRootView} from 'react-native-gesture-handler';
import {useOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import {useSharedValue} from 'react-native-reanimated';
import Animated, {FadeIn, useSharedValue} from 'react-native-reanimated';
import type {ValueOf} from 'type-fest';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL';
Expand Down Expand Up @@ -167,7 +166,6 @@ function AttachmentModal({
attachmentLink = '',
}: AttachmentModalProps) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const [isModalOpen, setIsModalOpen] = useState(defaultOpen);
const [shouldLoadAttachment, setShouldLoadAttachment] = useState(false);
const [isAttachmentInvalid, setIsAttachmentInvalid] = useState(false);
Expand All @@ -178,7 +176,6 @@ function AttachmentModal({
const [sourceState, setSourceState] = useState<AvatarSource>(() => source);
const [modalType, setModalType] = useState<ModalType>(CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE);
const [isConfirmButtonDisabled, setIsConfirmButtonDisabled] = useState(false);
const [confirmButtonFadeAnimation] = useState(() => new Animated.Value(1));
const [isDownloadButtonReadyToBeShown, setIsDownloadButtonReadyToBeShown] = React.useState(true);
const isPDFLoadError = useRef(false);
const {windowWidth} = useWindowDimensions();
Expand Down Expand Up @@ -590,7 +587,10 @@ function AttachmentModal({
{!!onConfirm && !isConfirmButtonDisabled && (
<SafeAreaConsumer>
{({safeAreaPaddingBottomStyle}) => (
<Animated.View style={[StyleUtils.fade(confirmButtonFadeAnimation), safeAreaPaddingBottomStyle]}>
<Animated.View
style={safeAreaPaddingBottomStyle}
entering={FadeIn}
>
<Button
ref={viewRef(submitRef)}
success
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {Animated} from 'react-native';
import Animated, {useAnimatedStyle} from 'react-native-reanimated';
import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -9,8 +9,9 @@ function GrowlNotificationContainer({children, translateY}: GrowlNotificationCon
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const insets = useSafeAreaInsets();
const animatedStyles = useAnimatedStyle(() => styles.growlNotificationTranslateY(translateY));

return <Animated.View style={[StyleUtils.getSafeAreaPadding(insets), styles.growlNotificationContainer, styles.growlNotificationTranslateY(translateY)]}>{children}</Animated.View>;
return <Animated.View style={[StyleUtils.getSafeAreaPadding(insets), styles.growlNotificationContainer, animatedStyles]}>{children}</Animated.View>;
}

GrowlNotificationContainer.displayName = 'GrowlNotificationContainer';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import React from 'react';
import {Animated} from 'react-native';
import Animated, {useAnimatedStyle} from 'react-native-reanimated';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import type GrowlNotificationContainerProps from './types';

function GrowlNotificationContainer({children, translateY}: GrowlNotificationContainerProps) {
const styles = useThemeStyles();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const animatedStyles = useAnimatedStyle(() => styles.growlNotificationTranslateY(translateY));

return (
<Animated.View
style={[styles.growlNotificationContainer, styles.growlNotificationDesktopContainer, styles.growlNotificationTranslateY(translateY), shouldUseNarrowLayout && styles.mwn]}
>
{children}
</Animated.View>
<Animated.View style={[styles.growlNotificationContainer, styles.growlNotificationDesktopContainer, animatedStyles, shouldUseNarrowLayout && styles.mwn]}>{children}</Animated.View>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type {Animated} from 'react-native';
import type {SharedValue} from 'react-native-reanimated';
import type ChildrenProps from '@src/types/utils/ChildrenProps';

type GrowlNotificationContainerProps = ChildrenProps & {
translateY: Animated.Value;
translateY: SharedValue<number>;
};

export default GrowlNotificationContainerProps;
19 changes: 11 additions & 8 deletions src/components/GrowlNotification/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type {ForwardedRef} from 'react';
import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
import {Animated, View} from 'react-native';
import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useState} from 'react';
import {View} from 'react-native';
import {Directions, Gesture, GestureDetector} from 'react-native-gesture-handler';
import {useSharedValue, withSpring} from 'react-native-reanimated';
import type {SvgProps} from 'react-native-svg';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
Expand All @@ -11,7 +12,6 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Growl from '@libs/Growl';
import type {GrowlRef} from '@libs/Growl';
import useNativeDriver from '@libs/useNativeDriver';
import CONST from '@src/CONST';
import GrowlNotificationContainer from './GrowlNotificationContainer';

Expand All @@ -20,7 +20,7 @@ const INACTIVE_POSITION_Y = -255;
const PressableWithoutFeedback = Pressables.PressableWithoutFeedback;

function GrowlNotification(_: unknown, ref: ForwardedRef<GrowlRef>) {
const translateY = useRef(new Animated.Value(INACTIVE_POSITION_Y)).current;
const translateY = useSharedValue(INACTIVE_POSITION_Y);
const [bodyText, setBodyText] = useState('');
const [type, setType] = useState('success');
const [duration, setDuration] = useState<number>();
Expand Down Expand Up @@ -76,10 +76,13 @@ function GrowlNotification(_: unknown, ref: ForwardedRef<GrowlRef>) {
*/
const fling = useCallback(
(val = INACTIVE_POSITION_Y) => {
Animated.spring(translateY, {
toValue: val,
useNativeDriver,
}).start();
'worklet';

translateY.set(
withSpring(val, {
overshootClamping: false,
}),
);
},
[translateY],
);
Expand Down
20 changes: 6 additions & 14 deletions src/components/TextInput/BaseTextInput/index.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {Str} from 'expensify-common';
import type {ForwardedRef} from 'react';
import React, {forwardRef, useCallback, useEffect, useRef, useState} from 'react';
import type {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, StyleProp, TextInput, TextInputFocusEventData, ViewStyle} from 'react-native';
import {ActivityIndicator, Animated, StyleSheet, View} from 'react-native';
import {ActivityIndicator, StyleSheet, View} from 'react-native';
import {useSharedValue, withSpring} from 'react-native-reanimated';
import Checkbox from '@components/Checkbox';
import FormHelpMessage from '@components/FormHelpMessage';
import Icon from '@components/Icon';
Expand All @@ -23,7 +24,6 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import getSecureEntryKeyboardType from '@libs/getSecureEntryKeyboardType';
import isInputAutoFilled from '@libs/isInputAutoFilled';
import useNativeDriver from '@libs/useNativeDriver';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type {BaseTextInputProps, BaseTextInputRef} from './types';
Expand Down Expand Up @@ -94,8 +94,8 @@ function BaseTextInput(
const [textInputHeight, setTextInputHeight] = useState(0);
const [height, setHeight] = useState<number>(variables.componentSizeLarge);
const [width, setWidth] = useState<number | null>(null);
const labelScale = useRef(new Animated.Value(initialActiveLabel ? styleConst.ACTIVE_LABEL_SCALE : styleConst.INACTIVE_LABEL_SCALE)).current;
const labelTranslateY = useRef(new Animated.Value(initialActiveLabel ? styleConst.ACTIVE_LABEL_TRANSLATE_Y : styleConst.INACTIVE_LABEL_TRANSLATE_Y)).current;
const labelScale = useSharedValue<number>(initialActiveLabel ? styleConst.ACTIVE_LABEL_SCALE : styleConst.INACTIVE_LABEL_SCALE);
const labelTranslateY = useSharedValue<number>(initialActiveLabel ? styleConst.ACTIVE_LABEL_TRANSLATE_Y : styleConst.INACTIVE_LABEL_TRANSLATE_Y);
const input = useRef<TextInput | null>(null);
const isLabelActive = useRef(initialActiveLabel);

Expand All @@ -117,16 +117,8 @@ function BaseTextInput(

const animateLabel = useCallback(
(translateY: number, scale: number) => {
Animated.parallel([
Animated.spring(labelTranslateY, {
toValue: translateY,
useNativeDriver,
}),
Animated.spring(labelScale, {
toValue: scale,
useNativeDriver,
}),
]).start();
labelScale.set(withSpring(scale, {overshootClamping: false}));
labelTranslateY.set(withSpring(translateY, {overshootClamping: false}));
},
[labelScale, labelTranslateY],
);
Expand Down
21 changes: 7 additions & 14 deletions src/components/TextInput/BaseTextInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {Str} from 'expensify-common';
import type {ForwardedRef} from 'react';
import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import type {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, StyleProp, TextInputFocusEventData, ViewStyle} from 'react-native';
import {ActivityIndicator, Animated, StyleSheet, View} from 'react-native';
import {ActivityIndicator, StyleSheet, View} from 'react-native';
import {useSharedValue, withSpring} from 'react-native-reanimated';
import Checkbox from '@components/Checkbox';
import FormHelpMessage from '@components/FormHelpMessage';
import Icon from '@components/Icon';
Expand All @@ -24,7 +25,6 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import isInputAutoFilled from '@libs/isInputAutoFilled';
import useNativeDriver from '@libs/useNativeDriver';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type {BaseTextInputProps, BaseTextInputRef} from './types';
Expand Down Expand Up @@ -99,8 +99,9 @@ function BaseTextInput(
const [height, setHeight] = useState<number>(variables.componentSizeLarge);
const [width, setWidth] = useState<number | null>(null);

const labelScale = useRef(new Animated.Value(initialActiveLabel ? styleConst.ACTIVE_LABEL_SCALE : styleConst.INACTIVE_LABEL_SCALE)).current;
const labelTranslateY = useRef(new Animated.Value(initialActiveLabel ? styleConst.ACTIVE_LABEL_TRANSLATE_Y : styleConst.INACTIVE_LABEL_TRANSLATE_Y)).current;
const labelScale = useSharedValue<number>(initialActiveLabel ? styleConst.ACTIVE_LABEL_SCALE : styleConst.INACTIVE_LABEL_SCALE);
const labelTranslateY = useSharedValue<number>(initialActiveLabel ? styleConst.ACTIVE_LABEL_TRANSLATE_Y : styleConst.INACTIVE_LABEL_TRANSLATE_Y);

const input = useRef<HTMLInputElement | null>(null);
const isLabelActive = useRef(initialActiveLabel);

Expand All @@ -122,16 +123,8 @@ function BaseTextInput(

const animateLabel = useCallback(
(translateY: number, scale: number) => {
Animated.parallel([
Animated.spring(labelTranslateY, {
toValue: translateY,
useNativeDriver,
}),
Animated.spring(labelScale, {
toValue: scale,
useNativeDriver,
}),
]).start();
labelScale.set(withSpring(scale, {overshootClamping: false}));
labelTranslateY.set(withSpring(translateY, {overshootClamping: false}));
},
[labelScale, labelTranslateY],
);
Expand Down
6 changes: 4 additions & 2 deletions src/components/TextInput/TextInputLabel/index.native.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import React from 'react';
import {Animated} from 'react-native';
import Animated, {useAnimatedStyle} from 'react-native-reanimated';
import useThemeStyles from '@hooks/useThemeStyles';
import type TextInputLabelProps from './types';

function TextInputLabel({label, labelScale, labelTranslateY}: TextInputLabelProps) {
const styles = useThemeStyles();

const animatedStyle = useAnimatedStyle(() => styles.textInputLabelTransformation(labelTranslateY, labelScale));

return (
<Animated.Text
allowFontScaling={false}
style={[styles.textInputLabel, styles.textInputLabelTransformation(labelTranslateY, labelScale)]}
style={[styles.textInputLabel, animatedStyle]}
>
{label}
</Animated.Text>
Expand Down
6 changes: 4 additions & 2 deletions src/components/TextInput/TextInputLabel/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {useEffect, useRef} from 'react';
// eslint-disable-next-line no-restricted-imports
import type {Text} from 'react-native';
import {Animated} from 'react-native';
import Animated, {useAnimatedStyle} from 'react-native-reanimated';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import textRef from '@src/types/utils/textRef';
Expand All @@ -19,12 +19,14 @@ function TextInputLabel({for: inputId = '', label, labelTranslateY, labelScale}:
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
}, []);

const animatedStyle = useAnimatedStyle(() => styles.textInputLabelTransformation(labelTranslateY, labelScale));

return (
<Animated.Text
// eslint-disable-next-line react-compiler/react-compiler
ref={textRef(labelRef)}
role={CONST.ROLE.PRESENTATION}
style={[styles.textInputLabel, styles.textInputLabelTransformation(labelTranslateY, labelScale), styles.pointerEventsNone]}
style={[styles.textInputLabel, animatedStyle, styles.pointerEventsNone]}
>
{label}
</Animated.Text>
Expand Down
6 changes: 3 additions & 3 deletions src/components/TextInput/TextInputLabel/types.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type {Animated} from 'react-native';
import type {SharedValue} from 'react-native-reanimated';

type TextInputLabelProps = {
/** Label */
label: string;

/** Label vertical translate */
labelTranslateY: Animated.Value;
labelTranslateY: SharedValue<number>;

/** Label scale */
labelScale: Animated.Value;
labelScale: SharedValue<number>;

/** For attribute for label */
for?: string;
Expand Down
25 changes: 16 additions & 9 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import type {LineLayerStyleProps} from '@rnmapbox/maps/src/utils/MapboxStyles';
import lodashClamp from 'lodash/clamp';
import type {LineLayer} from 'react-map-gl';
import type {AnimatableNumericValue, Animated, ImageStyle, TextStyle, ViewStyle} from 'react-native';
import type {Animated, ImageStyle, TextStyle, ViewStyle} from 'react-native';
import {Platform, StyleSheet} from 'react-native';
import type {CustomAnimation} from 'react-native-animatable';
import type {PickerStyle} from 'react-native-picker-select';
import type {SharedValue} from 'react-native-reanimated';
import type {MixedStyleDeclaration, MixedStyleRecord} from 'react-native-render-html';
import type {ValueOf} from 'type-fest';
import type DotLottieAnimation from '@components/LottieAnimations/types';
Expand Down Expand Up @@ -1213,10 +1214,13 @@ const styles = (theme: ThemeColors) =>
backgroundColor: theme.componentBG,
},

textInputLabelTransformation: (translateY: AnimatableNumericValue, scale: AnimatableNumericValue) =>
({
transform: [{translateY}, {scale}],
} satisfies TextStyle),
textInputLabelTransformation: (translateY: SharedValue<number>, scale: SharedValue<number>) => {
'worklet';

return {
transform: [{translateY: translateY.get()}, {scale: scale.get()}],
} satisfies TextStyle;
},

baseTextInput: {
...FontUtils.fontFamily.platform.EXP_NEUE,
Expand Down Expand Up @@ -3371,10 +3375,13 @@ const styles = (theme: ThemeColors) =>
...positioning.pFixed,
},

growlNotificationTranslateY: (translateY: AnimatableNumericValue) =>
({
transform: [{translateY}],
} satisfies ViewStyle),
growlNotificationTranslateY: (translateY: SharedValue<number>) => {
'worklet';

return {
transform: [{translateY: translateY.get()}],
};
},

makeSlideInTranslation: (translationType: Translation, fromValue: number) =>
({
Expand Down

0 comments on commit 034b2d9

Please sign in to comment.