lbry-desktop/ui/component/notification/view.jsx
infinite-persistence 02fdb1e6df
Notification: further handle "missed_out" + other tweaks (#6052)
* Show full notification text via tooltip

The tooltip fixes the system notifications problem (mentioned below), and also allows one to quickly read the entire comment without actually having to visit the comment.

Currently, we only show about 50 characters in the notification, truncating it to an ellipsis when exceeded.

This is not much of a problem for dynamic text (e.g. comments) since the full text can be seen after clicking on the notification (brings you to the comment). For system notifications, this is problematic since there's no other way to know what the full text was.

Tried to dynamically change the font size to auto fit, but it wasn't fruitful. Even if it did work, it'll probably won't be legible for a 2000-character comment, plus the entire list will look weird with various font sizes.

* Beautify "missed out" notification; bring user to Verify page.

## Issue
6021: Notifications: Missed Out

## Changes
- The notification already brings the user to the `/rewards`. Tweaked it to directly enter the Verify Page.
- Use LBC icon instead of generic bell for this notification.
2021-05-12 13:51:55 -04:00

207 lines
7.3 KiB
JavaScript

// @flow
import * as NOTIFICATIONS from 'constants/notifications';
import * as PAGES from 'constants/pages';
import * as ICONS from 'constants/icons';
import React from 'react';
import classnames from 'classnames';
import Icon from 'component/common/icon';
import DateTime from 'component/dateTime';
import Button from 'component/button';
import ChannelThumbnail from 'component/channelThumbnail';
import { formatLbryUrlForWeb } from 'util/url';
import { useHistory } from 'react-router';
import { parseURI } from 'lbry-redux';
import { PAGE_VIEW_QUERY, DISCUSSION_PAGE } from 'page/channel/view';
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';
type Props = {
notification: WebNotification,
menuButton: boolean,
children: any,
doReadNotifications: ([number]) => void,
doDeleteNotification: (number) => void,
};
export default function Notification(props: Props) {
const { notification, menuButton = false, doReadNotifications, doDeleteNotification } = props;
const { push } = useHistory();
const { notification_rule, notification_parameters, is_read, id } = notification;
const isCommentNotification =
notification_rule === NOTIFICATIONS.NOTIFICATION_COMMENT || notification_rule === NOTIFICATIONS.NOTIFICATION_REPLY;
const commentText = isCommentNotification && notification_parameters.dynamic.comment;
const channelUrl =
(notification_rule === NOTIFICATIONS.NEW_CONTENT && notification.notification_parameters.dynamic.channel_url) || '';
let notificationTarget;
switch (notification_rule) {
case NOTIFICATIONS.DAILY_WATCH_AVAILABLE:
case NOTIFICATIONS.DAILY_WATCH_REMIND:
notificationTarget = `/$/${PAGES.CHANNELS_FOLLOWING}`;
break;
case NOTIFICATIONS.MISSED_OUT:
notificationTarget = `/$/${PAGES.REWARDS_VERIFY}?redirect=/$/${PAGES.REWARDS}`;
break;
default:
notificationTarget = notification_parameters.device.target;
}
let notificationLink = formatLbryUrlForWeb(notificationTarget);
let urlParams = new URLSearchParams();
if (isCommentNotification && notification_parameters.dynamic.hash) {
urlParams.append('lc', notification_parameters.dynamic.hash);
}
try {
const { isChannel } = parseURI(notificationTarget);
if (isChannel) {
urlParams.append(PAGE_VIEW_QUERY, DISCUSSION_PAGE);
}
} catch (e) {}
notificationLink += `?${urlParams.toString()}`;
let icon;
switch (notification_rule) {
case NOTIFICATIONS.NOTIFICATION_CREATOR_SUBSCRIBER:
icon = <Icon icon={ICONS.SUBSCRIBE} sectionIcon />;
break;
case NOTIFICATIONS.NOTIFICATION_COMMENT:
icon = <ChannelThumbnail small uri={notification_parameters.dynamic.comment_author} />;
break;
case NOTIFICATIONS.NOTIFICATION_REPLY:
icon = <ChannelThumbnail small uri={notification_parameters.dynamic.reply_author} />;
break;
case NOTIFICATIONS.NEW_CONTENT:
icon = <ChannelThumbnail small uri={notification_parameters.dynamic.channel_url} />;
break;
case NOTIFICATIONS.NEW_LIVESTREAM:
icon = <ChannelThumbnail small uri={notification_parameters.dynamic.channel_url} />;
break;
case NOTIFICATIONS.DAILY_WATCH_AVAILABLE:
case NOTIFICATIONS.DAILY_WATCH_REMIND:
case NOTIFICATIONS.MISSED_OUT:
icon = <Icon icon={ICONS.LBC} sectionIcon />;
break;
default:
icon = <Icon icon={ICONS.NOTIFICATION} sectionIcon />;
}
function handleNotificationClick() {
if (!is_read) {
doReadNotifications([id]);
}
if (notificationLink) {
push(notificationLink);
}
}
function handleReadNotification(e) {
e.stopPropagation();
doReadNotifications([id]);
}
const Wrapper = menuButton
? (props: { children: any }) => (
<MenuItem className="menu__link--notification" onSelect={handleNotificationClick}>
{props.children}
</MenuItem>
)
: notificationLink
? (props: { children: any }) => (
<a className="menu__link--notification" onClick={handleNotificationClick}>
{props.children}
</a>
)
: (props: { children: any }) => (
<span
className={is_read ? 'menu__link--notification-nolink' : 'menu__link--notification'}
onClick={handleNotificationClick}
>
{props.children}
</span>
);
return (
<Wrapper>
<div
className={classnames('notification__wrapper', {
'notification__wrapper--unread': !is_read,
})}
>
<div className="notification__icon">{icon}</div>
<div className="notification__content-wrapper">
<div className="notification__content">
<div className="notification__text-wrapper">
{!isCommentNotification && (
<div className="notification__title">
<LbcMessage>{notification_parameters.device.title}</LbcMessage>
</div>
)}
{isCommentNotification && commentText ? (
<>
<div className="notification__title">
<LbcMessage>{notification_parameters.device.title}</LbcMessage>
</div>
<div title={commentText} className="notification__text mobile-hidden">
{commentText}
</div>
</>
) : (
<>
<div
title={notification_parameters.device.text.replace(/\sLBC/g, ' Credits')}
className="notification__text"
>
<LbcMessage>{notification_parameters.device.text}</LbcMessage>
</div>
</>
)}
</div>
{notification_rule === NOTIFICATIONS.NEW_CONTENT && (
<FileThumbnail uri={notification_parameters.device.target} className="notification__content-thumbnail" />
)}
{notification_rule === NOTIFICATIONS.NEW_LIVESTREAM && (
<FileThumbnail
thumbnail={notification_parameters.device.image_url}
className="notification__content-thumbnail"
/>
)}
</div>
<div className="notification__extra">
{!is_read && <Button className="notification__mark-seen" onClick={handleReadNotification} />}
<div className="notification__time">
<DateTime timeAgo date={notification.active_at} />
</div>
</div>
</div>
<div className="notification__menu">
<Menu>
<MenuButton onClick={(e) => 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 === NOTIFICATIONS.NEW_CONTENT && channelUrl ? (
<NotificationContentChannelMenu uri={channelUrl} />
) : null}
</MenuList>
</Menu>
</div>
</div>
</Wrapper>
);
}