2020-07-23 16:22:57 +02:00
|
|
|
// @flow
|
2020-09-15 16:00:35 +02:00
|
|
|
import * as PAGES from 'constants/pages';
|
2020-07-23 16:22:57 +02:00
|
|
|
import * as ICONS from 'constants/icons';
|
2021-07-08 04:50:51 +02:00
|
|
|
import { RULE } from 'constants/notifications';
|
2020-07-23 16:22:57 +02:00
|
|
|
import React from 'react';
|
2020-08-21 21:44:54 +02:00
|
|
|
import classnames from 'classnames';
|
2020-07-23 16:22:57 +02:00
|
|
|
import Icon from 'component/common/icon';
|
|
|
|
import DateTime from 'component/dateTime';
|
2020-08-31 19:12:34 +02:00
|
|
|
import Button from 'component/button';
|
2020-07-23 16:22:57 +02:00
|
|
|
import ChannelThumbnail from 'component/channelThumbnail';
|
|
|
|
import { formatLbryUrlForWeb } from 'util/url';
|
|
|
|
import { useHistory } from 'react-router';
|
2020-08-31 19:12:34 +02:00
|
|
|
import { parseURI } from 'lbry-redux';
|
|
|
|
import { PAGE_VIEW_QUERY, DISCUSSION_PAGE } from 'page/channel/view';
|
2020-11-02 17:51:08 +01:00
|
|
|
import FileThumbnail from 'component/fileThumbnail';
|
2020-11-03 21:09:56 +01:00
|
|
|
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
|
|
|
|
import NotificationContentChannelMenu from 'component/notificationContentChannelMenu';
|
2021-04-30 06:39:55 +02:00
|
|
|
import LbcMessage from 'component/common/lbc-message';
|
2021-08-18 23:40:36 +02:00
|
|
|
import UriIndicator from 'component/uriIndicator';
|
|
|
|
import { NavLink } from 'react-router-dom';
|
2021-08-27 12:29:58 +02:00
|
|
|
import CommentReactions from 'component/commentReactions';
|
|
|
|
import CommentCreate from 'component/commentCreate';
|
|
|
|
import CommentsReplies from 'component/commentsReplies';
|
2020-07-23 16:22:57 +02:00
|
|
|
|
|
|
|
type Props = {
|
|
|
|
notification: WebNotification,
|
|
|
|
menuButton: boolean,
|
|
|
|
children: any,
|
2020-12-14 19:52:17 +01:00
|
|
|
doReadNotifications: ([number]) => void,
|
2021-03-03 19:50:16 +01:00
|
|
|
doDeleteNotification: (number) => void,
|
2020-07-23 16:22:57 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export default function Notification(props: Props) {
|
2020-12-14 19:52:17 +01:00
|
|
|
const { notification, menuButton = false, doReadNotifications, doDeleteNotification } = props;
|
2020-07-23 16:22:57 +02:00
|
|
|
const { push } = useHistory();
|
2020-12-14 19:52:17 +01:00
|
|
|
const { notification_rule, notification_parameters, is_read, id } = notification;
|
2021-08-27 12:29:58 +02:00
|
|
|
const [isReplying, setReplying] = React.useState(false);
|
|
|
|
const [quickReply, setQuickReply] = React.useState();
|
2021-08-18 23:40:36 +02:00
|
|
|
|
2020-09-16 18:35:59 +02:00
|
|
|
const isCommentNotification =
|
2021-07-08 04:50:51 +02:00
|
|
|
notification_rule === RULE.COMMENT ||
|
|
|
|
notification_rule === RULE.COMMENT_REPLY ||
|
|
|
|
notification_rule === RULE.CREATOR_COMMENT;
|
2020-09-08 22:56:48 +02:00
|
|
|
const commentText = isCommentNotification && notification_parameters.dynamic.comment;
|
2020-09-16 18:35:59 +02:00
|
|
|
|
|
|
|
let notificationTarget;
|
|
|
|
switch (notification_rule) {
|
2021-07-08 04:50:51 +02:00
|
|
|
case RULE.DAILY_WATCH_AVAILABLE:
|
|
|
|
case RULE.DAILY_WATCH_REMIND:
|
2020-09-16 18:35:59 +02:00
|
|
|
notificationTarget = `/$/${PAGES.CHANNELS_FOLLOWING}`;
|
|
|
|
break;
|
2021-07-08 04:50:51 +02:00
|
|
|
case RULE.MISSED_OUT:
|
|
|
|
case RULE.REWARDS_APPROVAL_PROMPT:
|
2021-05-12 19:51:55 +02:00
|
|
|
notificationTarget = `/$/${PAGES.REWARDS_VERIFY}?redirect=/$/${PAGES.REWARDS}`;
|
|
|
|
break;
|
2020-09-16 18:35:59 +02:00
|
|
|
default:
|
|
|
|
notificationTarget = notification_parameters.device.target;
|
|
|
|
}
|
|
|
|
|
2021-08-18 23:40:36 +02:00
|
|
|
const creatorIcon = (channelUrl) => {
|
|
|
|
return (
|
|
|
|
<UriIndicator uri={channelUrl} link>
|
|
|
|
<ChannelThumbnail small uri={channelUrl} />
|
|
|
|
</UriIndicator>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
let channelUrl;
|
2020-07-23 16:22:57 +02:00
|
|
|
let icon;
|
2020-08-21 21:44:54 +02:00
|
|
|
switch (notification_rule) {
|
2021-07-08 04:50:51 +02:00
|
|
|
case RULE.CREATOR_SUBSCRIBER:
|
2020-11-13 18:58:31 +01:00
|
|
|
icon = <Icon icon={ICONS.SUBSCRIBE} sectionIcon />;
|
2020-07-23 16:22:57 +02:00
|
|
|
break;
|
2021-07-08 04:50:51 +02:00
|
|
|
case RULE.COMMENT:
|
|
|
|
case RULE.CREATOR_COMMENT:
|
2021-08-18 23:40:36 +02:00
|
|
|
channelUrl = notification_parameters.dynamic.comment_author;
|
|
|
|
icon = creatorIcon(channelUrl);
|
2020-07-23 16:22:57 +02:00
|
|
|
break;
|
2021-07-08 04:50:51 +02:00
|
|
|
case RULE.COMMENT_REPLY:
|
2021-08-18 23:40:36 +02:00
|
|
|
channelUrl = notification_parameters.dynamic.reply_author;
|
|
|
|
icon = creatorIcon(channelUrl);
|
2020-09-08 22:56:48 +02:00
|
|
|
break;
|
2021-07-08 04:50:51 +02:00
|
|
|
case RULE.NEW_CONTENT:
|
2021-08-18 23:40:36 +02:00
|
|
|
channelUrl = notification_parameters.dynamic.channel_url;
|
|
|
|
icon = creatorIcon(channelUrl);
|
2020-11-02 17:51:08 +01:00
|
|
|
break;
|
2021-07-08 04:50:51 +02:00
|
|
|
case RULE.NEW_LIVESTREAM:
|
2021-08-18 23:40:36 +02:00
|
|
|
channelUrl = notification_parameters.dynamic.channel_url;
|
|
|
|
icon = creatorIcon(channelUrl);
|
2021-04-16 21:53:33 +02:00
|
|
|
break;
|
2021-07-08 04:50:51 +02:00
|
|
|
case RULE.DAILY_WATCH_AVAILABLE:
|
|
|
|
case RULE.DAILY_WATCH_REMIND:
|
|
|
|
case RULE.MISSED_OUT:
|
|
|
|
case RULE.REWARDS_APPROVAL_PROMPT:
|
2020-11-13 06:36:23 +01:00
|
|
|
icon = <Icon icon={ICONS.LBC} sectionIcon />;
|
2020-10-22 18:40:09 +02:00
|
|
|
break;
|
2021-07-08 05:19:51 +02:00
|
|
|
case RULE.FIAT_TIP:
|
|
|
|
icon = <Icon icon={ICONS.FINANCE} sectionIcon />;
|
|
|
|
break;
|
2020-07-23 16:22:57 +02:00
|
|
|
default:
|
2020-11-13 18:58:31 +01:00
|
|
|
icon = <Icon icon={ICONS.NOTIFICATION} sectionIcon />;
|
2020-07-23 16:22:57 +02:00
|
|
|
}
|
|
|
|
|
2021-08-18 23:40:36 +02:00
|
|
|
let notificationLink = formatLbryUrlForWeb(notificationTarget);
|
|
|
|
let urlParams = new URLSearchParams();
|
|
|
|
if (isCommentNotification && notification_parameters.dynamic.hash) {
|
|
|
|
urlParams.append('lc', notification_parameters.dynamic.hash);
|
|
|
|
}
|
|
|
|
|
2021-09-22 17:28:32 +02:00
|
|
|
let channelName;
|
|
|
|
try {
|
|
|
|
const { claimName } = parseURI(channelUrl);
|
|
|
|
channelName = claimName;
|
|
|
|
} catch (e) {}
|
2021-08-18 23:40:36 +02:00
|
|
|
|
|
|
|
const notificationTitle = notification_parameters.device.title;
|
|
|
|
const titleSplit = notificationTitle.split(' ');
|
|
|
|
let fullTitle = [' '];
|
|
|
|
let uriIndicator;
|
|
|
|
const title = titleSplit.map((message, index) => {
|
|
|
|
if (channelName === message) {
|
|
|
|
uriIndicator = <UriIndicator uri={channelUrl} link />;
|
|
|
|
fullTitle.push(' ');
|
|
|
|
const resultTitle = fullTitle;
|
|
|
|
fullTitle = [' '];
|
|
|
|
|
|
|
|
return [resultTitle.join(' '), uriIndicator];
|
|
|
|
} else {
|
|
|
|
fullTitle.push(message);
|
|
|
|
|
|
|
|
if (index === titleSplit.length - 1) {
|
2021-08-27 12:29:58 +02:00
|
|
|
const result = fullTitle.join(' ');
|
|
|
|
return <LbcMessage key={result}>{result}</LbcMessage>;
|
2021-08-18 23:40:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { isChannel } = parseURI(notificationTarget);
|
|
|
|
if (isChannel) {
|
|
|
|
urlParams.append(PAGE_VIEW_QUERY, DISCUSSION_PAGE);
|
|
|
|
}
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
|
|
notificationLink += `?${urlParams.toString()}`;
|
|
|
|
const navLinkProps = {
|
|
|
|
to: notificationLink,
|
|
|
|
onClick: (e) => e.stopPropagation(),
|
|
|
|
};
|
|
|
|
|
2020-08-21 21:44:54 +02:00
|
|
|
function handleNotificationClick() {
|
2020-12-14 19:52:17 +01:00
|
|
|
if (!is_read) {
|
|
|
|
doReadNotifications([id]);
|
2020-08-21 21:44:54 +02:00
|
|
|
}
|
|
|
|
|
2021-08-18 23:40:36 +02:00
|
|
|
if (menuButton && notificationLink) {
|
2020-08-21 21:44:54 +02:00
|
|
|
push(notificationLink);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-23 16:22:57 +02:00
|
|
|
const Wrapper = menuButton
|
|
|
|
? (props: { children: any }) => (
|
2020-08-21 21:44:54 +02:00
|
|
|
<MenuItem className="menu__link--notification" onSelect={handleNotificationClick}>
|
2020-07-23 16:22:57 +02:00
|
|
|
{props.children}
|
|
|
|
</MenuItem>
|
|
|
|
)
|
2020-08-21 21:44:54 +02:00
|
|
|
: notificationLink
|
|
|
|
? (props: { children: any }) => (
|
2021-08-27 12:29:58 +02:00
|
|
|
<NavLink {...navLinkProps} className="menu__link--notification" onClick={handleNotificationClick}>
|
|
|
|
{props.children}
|
2021-08-18 23:40:36 +02:00
|
|
|
</NavLink>
|
2020-08-21 21:44:54 +02:00
|
|
|
)
|
|
|
|
: (props: { children: any }) => (
|
|
|
|
<span
|
2020-12-14 19:52:17 +01:00
|
|
|
className={is_read ? 'menu__link--notification-nolink' : 'menu__link--notification'}
|
2020-08-21 21:44:54 +02:00
|
|
|
onClick={handleNotificationClick}
|
|
|
|
>
|
|
|
|
{props.children}
|
|
|
|
</span>
|
2020-07-23 16:22:57 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
2021-08-27 12:29:58 +02:00
|
|
|
<div
|
|
|
|
className={classnames('notification__wrapper', {
|
|
|
|
'notification__wrapper--unread': !is_read,
|
|
|
|
})}
|
|
|
|
>
|
|
|
|
<Wrapper>
|
2020-07-23 16:22:57 +02:00
|
|
|
<div className="notification__icon">{icon}</div>
|
2020-07-30 22:14:12 +02:00
|
|
|
|
2020-11-03 19:45:36 +01:00
|
|
|
<div className="notification__content-wrapper">
|
|
|
|
<div className="notification__content">
|
|
|
|
<div className="notification__text-wrapper">
|
2021-08-18 23:40:36 +02:00
|
|
|
{!isCommentNotification && <div className="notification__title">{title}</div>}
|
2020-11-03 19:45:36 +01:00
|
|
|
|
|
|
|
{isCommentNotification && commentText ? (
|
|
|
|
<>
|
2021-08-18 23:40:36 +02:00
|
|
|
<div className="notification__title">{title}</div>
|
2021-08-26 16:44:00 +02:00
|
|
|
<div title={commentText} className="notification__text">
|
2021-05-12 19:51:55 +02:00
|
|
|
{commentText}
|
|
|
|
</div>
|
2020-11-03 19:45:36 +01:00
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
2021-05-12 19:51:55 +02:00
|
|
|
<div
|
|
|
|
title={notification_parameters.device.text.replace(/\sLBC/g, ' Credits')}
|
|
|
|
className="notification__text"
|
|
|
|
>
|
2021-04-30 06:39:55 +02:00
|
|
|
<LbcMessage>{notification_parameters.device.text}</LbcMessage>
|
|
|
|
</div>
|
2020-11-03 19:45:36 +01:00
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
|
2021-07-08 04:50:51 +02:00
|
|
|
{notification_rule === RULE.NEW_CONTENT && (
|
2021-04-16 21:53:33 +02:00
|
|
|
<FileThumbnail uri={notification_parameters.device.target} className="notification__content-thumbnail" />
|
|
|
|
)}
|
2021-07-08 04:50:51 +02:00
|
|
|
{notification_rule === RULE.NEW_LIVESTREAM && (
|
2021-04-16 21:53:33 +02:00
|
|
|
<FileThumbnail
|
|
|
|
thumbnail={notification_parameters.device.image_url}
|
|
|
|
className="notification__content-thumbnail"
|
|
|
|
/>
|
2020-08-21 21:44:54 +02:00
|
|
|
)}
|
2020-07-30 22:14:12 +02:00
|
|
|
</div>
|
|
|
|
|
2020-08-31 19:12:34 +02:00
|
|
|
<div className="notification__extra">
|
2021-08-27 12:29:58 +02:00
|
|
|
{!is_read && (
|
|
|
|
<Button
|
|
|
|
className="notification__mark-seen"
|
|
|
|
onClick={(e) => {
|
|
|
|
e.stopPropagation();
|
|
|
|
doReadNotifications([id]);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)}
|
2020-08-31 19:12:34 +02:00
|
|
|
<div className="notification__time">
|
2020-09-15 15:54:05 +02:00
|
|
|
<DateTime timeAgo date={notification.active_at} />
|
2020-08-31 19:12:34 +02:00
|
|
|
</div>
|
2020-07-23 16:22:57 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
2020-11-03 21:09:56 +01:00
|
|
|
|
|
|
|
<div className="notification__menu">
|
|
|
|
<Menu>
|
2021-08-18 23:40:36 +02:00
|
|
|
<MenuButton
|
|
|
|
className={'menu__button notification__menu-button'}
|
|
|
|
onClick={(e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
}}
|
|
|
|
>
|
2020-11-03 21:09:56 +01:00
|
|
|
<Icon size={18} icon={ICONS.MORE_VERTICAL} />
|
|
|
|
</MenuButton>
|
2021-03-03 19:50:16 +01:00
|
|
|
<MenuList className="menu__list">
|
2020-11-03 21:09:56 +01:00
|
|
|
<MenuItem className="menu__link" onSelect={() => doDeleteNotification(id)}>
|
|
|
|
<Icon aria-hidden icon={ICONS.DELETE} />
|
|
|
|
{__('Delete')}
|
|
|
|
</MenuItem>
|
2021-07-08 04:50:51 +02:00
|
|
|
{notification_rule === RULE.NEW_CONTENT && channelUrl ? (
|
2020-11-03 21:09:56 +01:00
|
|
|
<NotificationContentChannelMenu uri={channelUrl} />
|
|
|
|
) : null}
|
|
|
|
</MenuList>
|
|
|
|
</Menu>
|
|
|
|
</div>
|
2021-08-27 12:29:58 +02:00
|
|
|
</Wrapper>
|
|
|
|
|
|
|
|
{isCommentNotification && (
|
|
|
|
<div>
|
|
|
|
<div className="notification__reactions">
|
|
|
|
<Button
|
|
|
|
label={__('Reply')}
|
|
|
|
className="comment__action"
|
|
|
|
onClick={() => setReplying(!isReplying)}
|
|
|
|
icon={ICONS.REPLY}
|
|
|
|
/>
|
|
|
|
<CommentReactions
|
|
|
|
uri={notificationTarget}
|
|
|
|
commentId={notification_parameters.dynamic.hash}
|
|
|
|
hideCreatorLike
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{isReplying && (
|
|
|
|
<CommentCreate
|
|
|
|
isReply
|
|
|
|
uri={notificationTarget}
|
|
|
|
parentId={notification_parameters.dynamic.hash}
|
|
|
|
onDoneReplying={() => setReplying(false)}
|
|
|
|
onCancelReplying={() => setReplying(false)}
|
|
|
|
setQuickReply={setQuickReply}
|
|
|
|
supportDisabled
|
2021-08-27 14:03:29 +02:00
|
|
|
shouldFetchComment
|
2021-08-27 12:29:58 +02:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{quickReply && (
|
|
|
|
<CommentsReplies
|
|
|
|
uri={notificationTarget}
|
|
|
|
parentId={notification_parameters.dynamic.hash}
|
|
|
|
numDirectReplies={1}
|
|
|
|
supportDisabled
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
2020-07-23 16:22:57 +02:00
|
|
|
);
|
|
|
|
}
|