2023-02-08 21:10:26 +00:00
|
|
|
import "./Reactions.css";
|
|
|
|
|
|
|
|
import { useState, useMemo, useEffect } from "react";
|
|
|
|
import { useIntl, FormattedMessage } from "react-intl";
|
|
|
|
|
2023-02-11 20:05:46 +00:00
|
|
|
import { TaggedRawEvent } from "@snort/nostr";
|
2023-02-08 21:10:26 +00:00
|
|
|
|
|
|
|
import { formatShort } from "Number";
|
2023-03-02 17:47:02 +00:00
|
|
|
import Icon from "Icons/Icon";
|
2023-02-08 21:10:26 +00:00
|
|
|
import { Tab } from "Element/Tabs";
|
|
|
|
import { ParsedZap } from "Element/Zap";
|
|
|
|
import ProfileImage from "Element/ProfileImage";
|
|
|
|
import Tabs from "Element/Tabs";
|
|
|
|
import Modal from "Element/Modal";
|
|
|
|
|
|
|
|
import messages from "./messages";
|
|
|
|
|
|
|
|
interface ReactionsProps {
|
|
|
|
show: boolean;
|
|
|
|
setShow(b: boolean): void;
|
|
|
|
positive: TaggedRawEvent[];
|
|
|
|
negative: TaggedRawEvent[];
|
|
|
|
reposts: TaggedRawEvent[];
|
|
|
|
zaps: ParsedZap[];
|
|
|
|
}
|
|
|
|
|
2023-02-09 12:26:54 +00:00
|
|
|
const Reactions = ({ show, setShow, positive, negative, reposts, zaps }: ReactionsProps) => {
|
2023-02-08 21:10:26 +00:00
|
|
|
const { formatMessage } = useIntl();
|
|
|
|
const onClose = () => setShow(false);
|
|
|
|
const likes = useMemo(() => {
|
|
|
|
const sorted = [...positive];
|
|
|
|
sorted.sort((a, b) => b.created_at - a.created_at);
|
|
|
|
return sorted;
|
|
|
|
}, [positive]);
|
|
|
|
const dislikes = useMemo(() => {
|
|
|
|
const sorted = [...negative];
|
|
|
|
sorted.sort((a, b) => b.created_at - a.created_at);
|
|
|
|
return sorted;
|
|
|
|
}, [negative]);
|
2023-02-09 12:26:54 +00:00
|
|
|
const total = positive.length + negative.length + zaps.length + reposts.length;
|
2023-02-08 21:10:26 +00:00
|
|
|
const defaultTabs: Tab[] = [
|
|
|
|
{
|
|
|
|
text: formatMessage(messages.Likes, { n: likes.length }),
|
|
|
|
value: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: formatMessage(messages.Zaps, { n: zaps.length }),
|
|
|
|
value: 1,
|
|
|
|
disabled: zaps.length === 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: formatMessage(messages.Reposts, { n: reposts.length }),
|
|
|
|
value: 2,
|
|
|
|
disabled: reposts.length === 0,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
const tabs = defaultTabs.concat(
|
|
|
|
dislikes.length !== 0
|
|
|
|
? [
|
|
|
|
{
|
|
|
|
text: formatMessage(messages.Dislikes, { n: dislikes.length }),
|
|
|
|
value: 3,
|
|
|
|
},
|
|
|
|
]
|
|
|
|
: []
|
|
|
|
);
|
|
|
|
|
|
|
|
const [tab, setTab] = useState(tabs[0]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (!show) {
|
|
|
|
setTab(tabs[0]);
|
|
|
|
}
|
|
|
|
}, [show]);
|
|
|
|
|
|
|
|
return show ? (
|
|
|
|
<Modal className="reactions-modal" onClose={onClose}>
|
|
|
|
<div className="reactions-view">
|
|
|
|
<div className="close" onClick={onClose}>
|
2023-03-02 17:47:02 +00:00
|
|
|
<Icon name="close" />
|
2023-02-08 21:10:26 +00:00
|
|
|
</div>
|
|
|
|
<div className="reactions-header">
|
|
|
|
<h2>
|
2023-02-09 12:26:54 +00:00
|
|
|
<FormattedMessage {...messages.ReactionsCount} values={{ n: total }} />
|
2023-02-08 21:10:26 +00:00
|
|
|
</h2>
|
|
|
|
</div>
|
|
|
|
<Tabs tabs={tabs} tab={tab} setTab={setTab} />
|
|
|
|
<div className="body" key={tab.value}>
|
|
|
|
{tab.value === 0 &&
|
2023-02-09 12:26:54 +00:00
|
|
|
likes.map(ev => {
|
2023-02-08 21:10:26 +00:00
|
|
|
return (
|
|
|
|
<div key={ev.id} className="reactions-item">
|
2023-03-02 19:01:37 +00:00
|
|
|
<div className="reaction-icon">{ev.content === "+" ? <Icon name="heart" /> : ev.content}</div>
|
2023-02-12 21:40:02 +00:00
|
|
|
<ProfileImage autoWidth={false} pubkey={ev.pubkey} />
|
2023-02-08 21:10:26 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
{tab.value === 1 &&
|
2023-02-09 12:26:54 +00:00
|
|
|
zaps.map(z => {
|
2023-02-08 21:10:26 +00:00
|
|
|
return (
|
2023-03-05 16:58:34 +00:00
|
|
|
z.sender && (
|
2023-02-09 12:26:54 +00:00
|
|
|
<div key={z.id} className="reactions-item">
|
|
|
|
<div className="zap-reaction-icon">
|
2023-03-02 17:47:02 +00:00
|
|
|
<Icon name="zap" size={20} />
|
2023-02-09 12:26:54 +00:00
|
|
|
<span className="zap-amount">{formatShort(z.amount)}</span>
|
|
|
|
</div>
|
2023-02-18 21:27:06 +00:00
|
|
|
<ProfileImage
|
|
|
|
autoWidth={false}
|
2023-03-05 16:58:34 +00:00
|
|
|
pubkey={z.anonZap ? "" : z.sender}
|
2023-02-21 20:57:53 +00:00
|
|
|
subHeader={
|
|
|
|
<div className="f-ellipsis zap-comment" title={z.content}>
|
|
|
|
{z.content}
|
|
|
|
</div>
|
|
|
|
}
|
2023-02-18 21:27:06 +00:00
|
|
|
overrideUsername={z.anonZap ? formatMessage({ defaultMessage: "Anonymous" }) : undefined}
|
|
|
|
/>
|
2023-02-08 21:10:26 +00:00
|
|
|
</div>
|
2023-02-09 12:26:54 +00:00
|
|
|
)
|
2023-02-08 21:10:26 +00:00
|
|
|
);
|
|
|
|
})}
|
|
|
|
{tab.value === 2 &&
|
2023-02-09 12:26:54 +00:00
|
|
|
reposts.map(ev => {
|
2023-02-08 21:10:26 +00:00
|
|
|
return (
|
|
|
|
<div key={ev.id} className="reactions-item">
|
|
|
|
<div className="reaction-icon">
|
2023-03-02 17:47:02 +00:00
|
|
|
<Icon name="repost" size={16} />
|
2023-02-08 21:10:26 +00:00
|
|
|
</div>
|
2023-02-12 21:40:02 +00:00
|
|
|
<ProfileImage autoWidth={false} pubkey={ev.pubkey} />
|
2023-02-08 21:10:26 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
{tab.value === 3 &&
|
2023-02-09 12:26:54 +00:00
|
|
|
dislikes.map(ev => {
|
2023-02-08 21:10:26 +00:00
|
|
|
return (
|
|
|
|
<div key={ev.id} className="reactions-item">
|
|
|
|
<div className="reaction-icon">
|
2023-03-02 17:47:02 +00:00
|
|
|
<Icon name="dislike" />
|
2023-02-08 21:10:26 +00:00
|
|
|
</div>
|
2023-02-12 21:40:02 +00:00
|
|
|
<ProfileImage autoWidth={false} pubkey={ev.pubkey} />
|
2023-02-08 21:10:26 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Modal>
|
|
|
|
) : null;
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Reactions;
|