123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- import React, { useCallback, useContext, useEffect, useRef } from 'react';
- import { useTranslation } from 'react-i18next';
- import { Animated, Text, TextStyle, View, ViewStyle } from 'react-native';
-
- import Icon from '../../../base/icons/components/Icon';
- import {
- IconCloseLarge,
- IconInfoCircle,
- IconUsers,
- IconWarning
- } from '../../../base/icons/svg';
- import { colors } from '../../../base/ui/Tokens';
- import BaseTheme from '../../../base/ui/components/BaseTheme.native';
- import Button from '../../../base/ui/components/native/Button';
- import IconButton from '../../../base/ui/components/native/IconButton';
- import { BUTTON_MODES, BUTTON_TYPES } from '../../../base/ui/constants.native';
- import { CHAR_LIMIT } from '../../../chat/constants';
- import { replaceNonUnicodeEmojis } from '../../../chat/functions';
- import { NOTIFICATION_ICON, NOTIFICATION_TYPE } from '../../constants';
- import { INotificationProps } from '../../types';
- import { NotificationsTransitionContext } from '../NotificationsTransition';
-
- import styles from './styles';
-
-
- /**
- * Secondary colors for notification icons.
- *
- * @type {{error, info, normal, success, warning}}
- */
-
- const ICON_COLOR = {
- error: colors.error06,
- normal: colors.primary06,
- success: colors.success05,
- warning: colors.warning05
- };
-
-
- export interface IProps extends INotificationProps {
- _participants: ArrayLike<any>;
- onDismissed: Function;
- }
-
- const Notification = ({
- appearance = NOTIFICATION_TYPE.NORMAL,
- customActionHandler,
- customActionNameKey,
- customActionType,
- description,
- descriptionArguments,
- descriptionKey,
- icon,
- onDismissed,
- title,
- titleArguments,
- titleKey,
- uid
- }: IProps) => {
- const { t } = useTranslation();
- const notificationOpacityAnimation = useRef(new Animated.Value(0)).current;
- const { unmounting } = useContext(NotificationsTransitionContext);
-
- useEffect(() => {
- Animated.timing(
- notificationOpacityAnimation,
- {
- toValue: 1,
- duration: 200,
- useNativeDriver: true
- })
- .start();
- }, []);
-
- useEffect(() => {
- if (unmounting.get(uid ?? '')) {
- Animated.timing(
- notificationOpacityAnimation,
- {
- toValue: 0,
- duration: 200,
- useNativeDriver: true
- })
- .start();
- }
- }, [ unmounting ]);
-
- const onDismiss = useCallback(() => {
- onDismissed(uid);
- }, [ onDismissed, uid ]);
-
- const mapAppearanceToButtons = () => {
- if (customActionNameKey?.length && customActionHandler?.length && customActionType?.length) {
- return customActionNameKey?.map((customAction: string, index: number) => (
- <Button
- accessibilityLabel = { customAction }
- key = { index }
- labelKey = { customAction }
- mode = { BUTTON_MODES.TEXT }
- // eslint-disable-next-line react/jsx-no-bind
- onClick = { () => {
- if (customActionHandler[index]()) {
- onDismiss();
- }
- } }
- style = { styles.btn }
-
- // @ts-ignore
- type = { customActionType[index] } />
- ));
- }
-
- return [];
- };
-
- const getIcon = () => {
- let src;
-
- switch (icon || appearance) {
- case NOTIFICATION_ICON.PARTICIPANT:
- src = IconInfoCircle;
- break;
- case NOTIFICATION_ICON.PARTICIPANTS:
- src = IconUsers;
- break;
- case NOTIFICATION_ICON.WARNING:
- src = IconWarning;
- break;
- default:
- src = IconInfoCircle;
- break;
- }
-
- return src;
- };
-
- const _getDescription = () => {
- const descriptionArray = [];
-
- descriptionKey
- && descriptionArray.push(t(descriptionKey, descriptionArguments));
-
- description && descriptionArray.push(description);
-
- return descriptionArray;
- };
-
- // eslint-disable-next-line react/no-multi-comp
- const _renderContent = () => {
- const titleText = title || (titleKey && t(titleKey, titleArguments));
- const descriptionArray = _getDescription();
-
- if (descriptionArray?.length) {
- return (
- <>
- <Text
- numberOfLines = { 1 }
- style = { styles.contentTextTitle as TextStyle }>
- { titleText }
- </Text>
- {
- descriptionArray.map((line, index) => (
- <Text
- key = { index }
- numberOfLines = { 3 }
- style = { styles.contentText }>
- { line.length >= CHAR_LIMIT ? line : replaceNonUnicodeEmojis(line) }
- </Text>
- ))
- }
- </>
- );
- }
-
- return (
- <Text
- numberOfLines = { 1 }
- style = { styles.contentTextTitle as TextStyle }>
- { titleText }
- </Text>
- );
- };
-
- return (
- <Animated.View
- pointerEvents = 'box-none'
- style = { [
- _getDescription()?.length
- ? styles.notificationWithDescription
- : styles.notification,
- {
- opacity: notificationOpacityAnimation
- }
- ] as ViewStyle[] }>
- <View
- style = { (icon === NOTIFICATION_ICON.PARTICIPANTS
- ? styles.contentColumn
- : styles.interactiveContentColumn) as ViewStyle }>
- <View style = { styles.iconContainer as ViewStyle }>
- <Icon
- color = { ICON_COLOR[appearance as keyof typeof ICON_COLOR] }
- size = { 24 }
- src = { getIcon() } />
- </View>
- <View
- pointerEvents = 'box-none'
- style = { styles.contentContainer }>
- { _renderContent() }
- </View>
- <View style = { styles.btnContainer as ViewStyle }>
- { mapAppearanceToButtons() }
- </View>
- </View>
- <IconButton
- color = { BaseTheme.palette.icon04 }
- onPress = { onDismiss }
- src = { IconCloseLarge }
- type = { BUTTON_TYPES.TERTIARY } />
- </Animated.View>
- );
-
- };
-
- export default Notification;
|