import React, { useState, useEffect, useMemo } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actions from 'loot-core/src/client/actions';
import {
View,
Text,
Button,
ButtonWithLoading,
Stack,
ExternalLink
} from 'loot-design/src/components/common';
import { styles, colors } from 'loot-design/src/style';
import Delete from 'loot-design/src/svg/Delete';
import Loading from 'loot-design/src/svg/v1/AnimatedLoading';
function compileMessage(message, actions, setLoading, onRemove) {
return (
{message.split(/\n\n/).map((paragraph, idx) => {
let parts = paragraph.split(/(\[[^\]]*\]\([^)]*\))/g);
return (
{parts.map((part, idx) => {
let match = part.match(/\[([^\]]*)\]\(([^)]*)\)/);
if (match) {
let [_, text, href] = match;
if (href[0] === '#') {
let actionName = href.slice(1);
return (
// eslint-disable-next-line
{
e.preventDefault();
if (actions[actionName]) {
setLoading(true);
await actions[actionName]();
onRemove();
}
}}
>
{text}
);
}
return (
{match[1]}
);
}
return {part};
})}
);
})}
);
}
function Notification({ notification, onRemove }) {
let {
id,
type,
title,
message,
messageActions,
sticky,
internal,
button
} = notification;
let [loading, setLoading] = useState(false);
let [overlayLoading, setOverlayLoading] = useState(false);
useEffect(() => {
if (type === 'error' && internal) {
console.error('Internal error:', internal);
}
if (!sticky) {
setTimeout(onRemove, 6500);
}
}, []);
let positive = type === 'message';
let error = type === 'error';
let processedMessage = useMemo(
() => compileMessage(message, messageActions, setOverlayLoading, onRemove),
[message, messageActions]
);
return (
{title && (
{title}
)}
{processedMessage}
{button && (
{
setLoading(true);
await button.action();
onRemove();
setLoading(false);
}}
style={{
backgroundColor: 'transparent',
border: `1px solid ${
positive ? colors.g5 : error ? colors.r4 : colors.y3
}`,
color: 'currentColor',
fontSize: 14,
flexShrink: 0,
'&:hover, &:active': {
backgroundColor: positive
? colors.g9
: error
? colors.r10
: colors.y9
}
}}
>
{button.title}
)}
{sticky && (
)}
{overlayLoading && (
)}
);
}
function Notifications({ notifications, removeNotification, style }) {
return (
{notifications.map(note => (
{
if (note.onClose) {
note.onClose();
}
removeNotification(note.id);
}}
/>
))}
);
}
export default connect(
state => ({ notifications: state.notifications.notifications }),
dispatch => bindActionCreators(actions, dispatch)
)(Notifications);