UNPKG

@iterable/react-native-sdk

Version:
309 lines (304 loc) 8.79 kB
"use strict"; import { useRef } from 'react'; import { Animated, Image, PanResponder, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { ITERABLE_INBOX_COLORS } from "../constants/index.js"; /** * Renders a default layout for a message list item in the inbox. * * TODO: Change to component * * @param last - Indicates if this is the last item in the list. * @param dataModel - The data model containing the message data. * @param rowViewModel - The view model for the current row. * @param customizations - Custom styles and configurations. * @param isPortrait - Indicates if the device is in portrait mode. */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; function defaultMessageListLayout(last, dataModel, rowViewModel, customizations, isPortrait) { const messageTitle = rowViewModel.inAppMessage.inboxMetadata?.title ?? ''; const messageBody = rowViewModel.inAppMessage.inboxMetadata?.subtitle ?? ''; const messageCreatedAt = dataModel.getFormattedDate(rowViewModel.inAppMessage) ?? ''; const thumbnailURL = rowViewModel.imageUrl; const styles = StyleSheet.create({ body: { color: ITERABLE_INBOX_COLORS.TEXT_MUTED, flexWrap: 'wrap', fontSize: 15, paddingBottom: 10, width: '85%' }, createdAt: { color: ITERABLE_INBOX_COLORS.TEXT_MUTED, fontSize: 12 }, messageContainer: { flexDirection: 'column', justifyContent: 'center', paddingLeft: 10, width: '75%' }, messageRow: { backgroundColor: ITERABLE_INBOX_COLORS.CONTAINER_BACKGROUND_LIGHT, borderColor: ITERABLE_INBOX_COLORS.BORDER, borderStyle: 'solid', borderTopWidth: 1, flexDirection: 'row', height: 150, paddingBottom: 10, paddingTop: 10, width: '100%' }, readMessageThumbnailContainer: { flexDirection: 'column', justifyContent: 'center', paddingLeft: 30 }, title: { fontSize: 22, paddingBottom: 10, width: '85%' }, unreadIndicator: { backgroundColor: ITERABLE_INBOX_COLORS.UNREAD, borderRadius: 15 / 2, height: 15, marginLeft: 10, marginRight: 5, marginTop: 10, width: 15 }, unreadIndicatorContainer: { flexDirection: 'column', height: '100%', justifyContent: 'flex-start' }, unreadMessageThumbnailContainer: { flexDirection: 'column', justifyContent: 'center', paddingLeft: 10 } }); const resolvedStyles = { ...styles, ...customizations }; const { unreadIndicatorContainer, unreadMessageThumbnailContainer, title, body, createdAt, messageRow } = resolvedStyles; let { unreadIndicator, readMessageThumbnailContainer, messageContainer } = resolvedStyles; unreadIndicator = !isPortrait ? { ...unreadIndicator, marginLeft: 40 } : unreadIndicator; readMessageThumbnailContainer = !isPortrait ? { ...readMessageThumbnailContainer, paddingLeft: 65 } : readMessageThumbnailContainer; messageContainer = !isPortrait ? { ...messageContainer, width: '90%' } : messageContainer; function messageRowStyle(_rowViewModel) { return last ? { ...messageRow, borderBottomWidth: 1 } : messageRow; } return /*#__PURE__*/_jsxs(View, { style: messageRowStyle(rowViewModel), children: [/*#__PURE__*/_jsx(View, { style: unreadIndicatorContainer, children: rowViewModel.read ? null : /*#__PURE__*/_jsx(View, { style: unreadIndicator }) }), /*#__PURE__*/_jsx(View, { style: rowViewModel.read ? readMessageThumbnailContainer : unreadMessageThumbnailContainer, children: thumbnailURL ? /*#__PURE__*/_jsx(Image // MOB-10429: Use stylesheet according to best practices // eslint-disable-next-line react-native/no-inline-styles , { style: { height: 80, width: 80 }, source: { uri: thumbnailURL } }) : null }), /*#__PURE__*/_jsxs(View, { style: messageContainer, children: [/*#__PURE__*/_jsx(Text, { numberOfLines: 1, ellipsizeMode: "tail", style: title, children: messageTitle }), /*#__PURE__*/_jsx(Text, { numberOfLines: 3, ellipsizeMode: "tail", style: body, children: messageBody }), /*#__PURE__*/_jsx(Text, { style: createdAt, children: messageCreatedAt })] })] }); } /** * Props for the IterableInboxMessageCell component. */ /** * Component which renders a single message cell in the Iterable inbox. */ export const IterableInboxMessageCell = ({ index, last, dataModel, rowViewModel, customizations, swipingCheck, messageListItemLayout, deleteRow, handleMessageSelect, contentWidth, isPortrait }) => { const position = useRef(new Animated.ValueXY()).current; let deleteSliderHeight = customizations.messageRow?.height ? customizations.messageRow.height : 150; if (messageListItemLayout(last, rowViewModel)) { deleteSliderHeight = messageListItemLayout(last, rowViewModel)?.[1] ?? deleteSliderHeight; } const styles = StyleSheet.create({ deleteSlider: { alignItems: 'center', backgroundColor: ITERABLE_INBOX_COLORS.DESTRUCTIVE, elevation: 1, flexDirection: 'row', height: deleteSliderHeight, justifyContent: 'flex-end', paddingRight: 10, position: 'absolute', width: '100%', ...(isPortrait ? {} : { paddingRight: 40 }) }, textContainer: { elevation: 2, width: '100%' }, textStyle: { color: ITERABLE_INBOX_COLORS.TEXT_INVERSE, fontSize: 15, fontWeight: 'bold' } }); const scrollThreshold = contentWidth / 15; const FORCING_DURATION = 350; //If user swipes, either complete swipe or reset function userSwipedLeft(gesture) { if (gesture.dx < -0.6 * contentWidth) { completeSwipe(); } else { resetPosition(); } } function completeSwipe() { const x = -2000; Animated.timing(position, { toValue: { x, y: 0 }, duration: FORCING_DURATION, useNativeDriver: false }).start(() => deleteRow(rowViewModel.inAppMessage.messageId)); } function resetPosition() { Animated.timing(position, { toValue: { x: 0, y: 0 }, duration: 200, useNativeDriver: false }).start(); } const panResponder = useRef(PanResponder.create({ onStartShouldSetPanResponder: () => false, onMoveShouldSetPanResponder: (_event, gestureState) => { const { dx, dy } = gestureState; // return true if user is swiping, return false if it's a single click return Math.abs(dx) !== 0 && Math.abs(dy) !== 0; }, onMoveShouldSetPanResponderCapture: (_event, gestureState) => { const { dx, dy } = gestureState; // return true if user is swiping, return false if it's a single click return Math.abs(dx) !== 0 && Math.abs(dy) !== 0; }, onPanResponderTerminationRequest: () => false, onPanResponderGrant: () => { position.setValue({ x: 0, y: 0 }); }, onPanResponderMove: (_event, gesture) => { if (gesture.dx <= -scrollThreshold) { //enables swipeing when threshold is reached swipingCheck(true); //threshold value is deleted from movement const x = gesture.dx; //position is set to the new value position.setValue({ x, y: 0 }); } }, onPanResponderRelease: (_event, gesture) => { position.flattenOffset(); if (gesture.dx < 0) { userSwipedLeft(gesture); } else { resetPosition(); } swipingCheck(false); } })).current; return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx(View, { style: styles.deleteSlider, children: /*#__PURE__*/_jsx(Text, { style: styles.textStyle, children: "DELETE" }) }), /*#__PURE__*/_jsx(Animated.View, { style: [styles.textContainer, position.getLayout()], ...panResponder.panHandlers, children: /*#__PURE__*/_jsx(TouchableOpacity, { activeOpacity: 1, onPress: () => { handleMessageSelect(rowViewModel.inAppMessage.messageId, index); }, children: messageListItemLayout(last, rowViewModel) ? messageListItemLayout(last, rowViewModel)?.[0] : defaultMessageListLayout(last, dataModel, rowViewModel, customizations, isPortrait) }) })] }); }; //# sourceMappingURL=IterableInboxMessageCell.js.map