lbry-desktop/ui/component/notification/view.jsx

309 lines
9.9 KiB
React
Raw Normal View History

2020-07-23 16:22:57 +02:00
// @flow
import * as PAGES from 'constants/pages';
2020-07-23 16:22:57 +02:00
import * as ICONS from 'constants/icons';
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';
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';
import { parseURI } from 'util/lbryURI';
import { PAGE_VIEW_QUERY, DISCUSSION_PAGE } from 'page/channel/view';
2020-11-02 17:51:08 +01:00
import FileThumbnail from 'component/fileThumbnail';
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
import NotificationContentChannelMenu from 'component/notificationContentChannelMenu';
import LbcMessage from 'component/common/lbc-message';
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,
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();
const isCommentNotification =
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;
let notificationTarget;
switch (notification_rule) {
case RULE.DAILY_WATCH_AVAILABLE:
case RULE.DAILY_WATCH_REMIND:
notificationTarget = `/$/${PAGES.CHANNELS_FOLLOWING}`;
break;
case RULE.MISSED_OUT:
case RULE.REWARDS_APPROVAL_PROMPT:
notificationTarget = `/$/${PAGES.REWARDS_VERIFY}?redirect=/$/${PAGES.REWARDS}`;
break;
default:
notificationTarget = notification_parameters.device.target;
}
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) {
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;
case RULE.COMMENT:
case RULE.CREATOR_COMMENT:
channelUrl = notification_parameters.dynamic.comment_author;
icon = creatorIcon(channelUrl);
2020-07-23 16:22:57 +02:00
break;
case RULE.COMMENT_REPLY:
channelUrl = notification_parameters.dynamic.reply_author;
icon = creatorIcon(channelUrl);
2020-09-08 22:56:48 +02:00
break;
case RULE.NEW_CONTENT:
channelUrl = notification_parameters.dynamic.channel_url;
icon = creatorIcon(channelUrl);
2020-11-02 17:51:08 +01:00
break;
case RULE.NEW_LIVESTREAM:
channelUrl = notification_parameters.dynamic.channel_url;
icon = creatorIcon(channelUrl);
2021-04-16 21:53:33 +02:00
break;
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;
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
}
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;
2021-10-14 22:46:36 +02:00
if (channelUrl) {
try {
const { claimName } = parseURI(channelUrl);
channelName = claimName;
} catch (e) {}
}
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>;
}
}
});
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
}
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}
</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-11-03 19:45:36 +01:00
<div className="notification__content-wrapper">
<div className="notification__content">
<div className="notification__text-wrapper">
{!isCommentNotification && <div className="notification__title">{title}</div>}
2020-11-03 19:45:36 +01:00
{isCommentNotification && commentText ? (
<>
<div className="notification__title">{title}</div>
2021-08-26 16:44:00 +02:00
<div title={commentText} className="notification__text">
{commentText}
</div>
2020-11-03 19:45:36 +01:00
</>
) : (
<>
<div
title={notification_parameters.device.text.replace(/\sLBC/g, ' Credits')}
className="notification__text"
>
<LbcMessage>{notification_parameters.device.text}</LbcMessage>
</div>
2020-11-03 19:45:36 +01:00
</>
)}
</div>
{notification_rule === RULE.NEW_CONTENT && (
2021-04-16 21:53:33 +02:00
<FileThumbnail uri={notification_parameters.device.target} className="notification__content-thumbnail" />
)}
{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
)}
</div>
<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]);
}}
/>
)}
<div className="notification__time">
2020-09-15 15:54:05 +02:00
<DateTime timeAgo date={notification.active_at} />
</div>
2020-07-23 16:22:57 +02:00
</div>
</div>
<div className="notification__menu">
<Menu>
<MenuButton
className={'menu__button notification__menu-button'}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<Icon size={18} icon={ICONS.MORE_VERTICAL} />
</MenuButton>
<MenuList className="menu__list">
<MenuItem className="menu__link" onSelect={() => doDeleteNotification(id)}>
<Icon aria-hidden icon={ICONS.DELETE} />
{__('Delete')}
</MenuItem>
{notification_rule === RULE.NEW_CONTENT && channelUrl ? (
<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
);
}