Files
2024-12-18 13:05:28 +00:00

166 lines
4.9 KiB
TypeScript

import React, { useEffect, useState } from "react";
import { StyledLottie } from "../styled-lottie/StyledLottie";
import {
NativeEventEmitter,
NativeModules,
Platform,
ViewStyle,
useWindowDimensions,
} from "react-native";
import {
PanGestureHandler,
State,
TapGestureHandler,
} from "react-native-gesture-handler";
import Animated, {
clamp,
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
} from "react-native-reanimated";
import { GenericActionPayload } from "../../../App/common/actions/GenericAction";
import {
FAB_WIDTH_LARGE,
FAB_WIDTH_SMALL,
FabIconSize,
OsTypeConstants,
} from "../../../App/common/constants";
import { NativeEventNameConstants } from "../../../App/common/constants/EventNameConstants";
import { CtaData } from "../../../App/common/interface";
import { FabWidgetData } from "../../../App/common/interface/widgets/widgetData/FabWidgetData";
import { getTextWithHtmlSpace } from "../../../App/common/utilities/MiscUtils";
import { StyledImage } from "../../StyledImage";
import { createStyles } from "./FABStyle";
const FAB = ({
widgetData,
handleActions,
handleClick,
scrollStyle,
}: {
widgetData: FabWidgetData;
handleActions: (
value: any | undefined | null,
actionPayloadList: GenericActionPayload | undefined,
) => void;
handleClick?: (cta: CtaData) => void;
scrollStyle?: ViewStyle;
}) => {
const [enabled, setEnabled] = useState(true);
const { height } = useWindowDimensions();
useEffect(() => {
const nativeEventListener =
Platform.OS === OsTypeConstants.ANDROID
? new NativeEventEmitter()
: new NativeEventEmitter(NativeModules.DeviceEventEmitterModule);
let reloadPageEventListener = nativeEventListener.addListener(
NativeEventNameConstants.reloadPage,
event => {
if (event === true) {
setEnabled(false);
}
},
);
return () => {
nativeEventListener.removeAllListeners(
NativeEventNameConstants.reloadPage,
);
setEnabled(true);
};
}, [widgetData]);
const FAB_STARTING_POSITION = widgetData?.properties?.startingPosition ?? 145;
const getFabWidth = (fabIconSize?: string) =>
fabIconSize === FabIconSize.SMALL ? FAB_WIDTH_SMALL : FAB_WIDTH_LARGE;
const FAB_WIDTH = getFabWidth(widgetData?.properties?.fabIconSize);
const styles = createStyles(FAB_WIDTH);
const FAB_HEIGHT = FAB_WIDTH;
const fabPositionY = useSharedValue(-FAB_STARTING_POSITION);
const _onTapHandlerStateChange = ({ nativeEvent }: { nativeEvent: any }) => {
if (
handleClick &&
widgetData?.callbackCta &&
nativeEvent.state === State.ACTIVE
) {
handleClick(widgetData?.callbackCta);
}
};
const _onPanHandlerStateChange = useAnimatedGestureHandler({
onStart: (_, ctx) => {
ctx.startY = fabPositionY.value;
},
onActive: (event, ctx: any) => {
const newY = ctx.startY + event.translationY;
const minY = -height + 2 * FAB_HEIGHT;
const maxY = 0;
fabPositionY.value = clamp(newY, minY, maxY);
},
onEnd: _ => {},
});
const animatedRootStyles = useAnimatedStyle(() => {
return {
transform: [{ translateY: fabPositionY.value }],
};
});
const isDraggable = widgetData?.properties?.isDraggable ?? true;
const buttonText = getTextWithHtmlSpace(widgetData?.buttonTitle?.text);
const fabContent = (
<Animated.View style={[styles.rootStyles, animatedRootStyles]}>
<TapGestureHandler
enabled={enabled}
onHandlerStateChange={_onTapHandlerStateChange}
>
<Animated.View style={styles.fabButtonStyles}>
{widgetData.topLottieData && (
<Animated.View style={styles.topLottie}>
<StyledLottie lottieFieldData={widgetData?.topLottieData} />
</Animated.View>
)}
{widgetData?.imageData && (
<Animated.View style={styles.image}>
<StyledImage imageFieldData={widgetData?.imageData} />
</Animated.View>
)}
{widgetData?.buttonTitle?.text && (
<Animated.View style={[styles.buttonTitle, scrollStyle]}>
<Animated.Text style={widgetData?.buttonTitle?.textStyle}>
{buttonText}
</Animated.Text>
</Animated.View>
)}
{widgetData.lottieData &&
!!!widgetData.topLottieData &&
!!!widgetData.imageData &&
!!!widgetData.buttonTitle?.text && (
<Animated.View style={styles.lottie}>
<StyledLottie lottieFieldData={widgetData?.lottieData} />
</Animated.View>
)}
</Animated.View>
</TapGestureHandler>
</Animated.View>
);
/* remove backward compatibility code in next release */
return isDraggable ? (
<PanGestureHandler onHandlerStateChange={_onPanHandlerStateChange}>
{fabContent}
</PanGestureHandler>
) : (
fabContent
);
};
export default FAB;