import "./ProfilePage.css";
import { useEffect, useState } from "react";
import { useIntl, FormattedMessage } from "react-intl";
import { useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
import { encodeTLV, EventKind, HexKey, NostrPrefix } from "@snort/nostr";
import { parseNostrLink, getReactions, unwrap } from "Util";
import { formatShort } from "Number";
import Note from "Element/Note";
import Bookmarks from "Element/Bookmarks";
import RelaysMetadata from "Element/RelaysMetadata";
import { Tab, TabElement } from "Element/Tabs";
import Icon from "Icons/Icon";
import useMutedFeed from "Feed/MuteList";
import useRelaysFeed from "Feed/RelaysFeed";
import usePinnedFeed from "Feed/PinnedFeed";
import useBookmarkFeed from "Feed/BookmarkFeed";
import useFollowersFeed from "Feed/FollowersFeed";
import useFollowsFeed from "Feed/FollowsFeed";
import useProfileBadges from "Feed/BadgesFeed";
import { useUserProfile } from "Hooks/useUserProfile";
import useModeration from "Hooks/useModeration";
import useZapsFeed from "Feed/ZapsFeed";
import { default as ZapElement } from "Element/Zap";
import FollowButton from "Element/FollowButton";
import { extractLnAddress, parseId, hexToBech32 } from "Util";
import Avatar from "Element/Avatar";
import Timeline from "Element/Timeline";
import Text from "Element/Text";
import SendSats from "Element/SendSats";
import Nip05 from "Element/Nip05";
import Copy from "Element/Copy";
import ProfileImage from "Element/ProfileImage";
import BlockList from "Element/BlockList";
import MutedList from "Element/MutedList";
import FollowsList from "Element/FollowListBase";
import IconButton from "Element/IconButton";
import { RootState } from "State/Store";
import FollowsYou from "Element/FollowsYou";
import QrCode from "Element/QrCode";
import Modal from "Element/Modal";
import BadgeList from "Element/BadgeList";
import { ProxyImg } from "Element/ProxyImg";
import useHorizontalScroll from "Hooks/useHorizontalScroll";
import messages from "./messages";
import { EmailRegex } from "Const";
import { getNip05PubKey } from "./Login";
const NOTES = 0;
const REACTIONS = 1;
const FOLLOWERS = 2;
const FOLLOWS = 3;
const ZAPS = 4;
const MUTED = 5;
const BLOCKED = 6;
const RELAYS = 7;
const BOOKMARKS = 8;
function ZapsProfileTab({ id }: { id: HexKey }) {
const zaps = useZapsFeed(id);
const zapsTotal = zaps.reduce((acc, z) => acc + z.amount, 0);
return (
);
}
function FollowersTab({ id }: { id: HexKey }) {
const followers = useFollowersFeed(id);
return ;
}
function FollowsTab({ id }: { id: HexKey }) {
const follows = useFollowsFeed(id);
return ;
}
function RelaysTab({ id }: { id: HexKey }) {
const relays = useRelaysFeed(id);
return ;
}
function BookMarksTab({ id }: { id: HexKey }) {
const bookmarks = useBookmarkFeed(id);
return ;
}
export default function ProfilePage() {
const { formatMessage } = useIntl();
const params = useParams();
const navigate = useNavigate();
const [id, setId] = useState();
const user = useUserProfile(id);
const loginPubKey = useSelector((s: RootState) => s.login.publicKey);
const isMe = loginPubKey === id;
const [showLnQr, setShowLnQr] = useState(false);
const [showProfileQr, setShowProfileQr] = useState(false);
const aboutText = user?.about || "";
const about = Text({
content: aboutText,
tags: [],
creator: "",
disableMedia: true,
});
const npub = !id?.startsWith(NostrPrefix.PublicKey) ? hexToBech32(NostrPrefix.PublicKey, id || undefined) : id;
const lnurl = extractLnAddress(user?.lud16 || user?.lud06 || "");
const website_url =
user?.website && !user.website.startsWith("http") ? "https://" + user.website : user?.website || "";
// feeds
const { blocked } = useModeration();
const pinned = usePinnedFeed(id);
const muted = useMutedFeed(id);
const badges = useProfileBadges(id);
const follows = useFollowsFeed(id);
// tabs
const ProfileTab = {
Notes: { text: formatMessage(messages.Notes), value: NOTES },
Reactions: { text: formatMessage(messages.Reactions), value: REACTIONS },
Followers: { text: formatMessage(messages.Followers), value: FOLLOWERS },
Follows: { text: formatMessage(messages.Follows), value: FOLLOWS },
Zaps: { text: formatMessage(messages.Zaps), value: ZAPS },
Muted: { text: formatMessage(messages.Muted), value: MUTED },
Blocked: { text: formatMessage(messages.BlockedCount, { n: blocked.length }), value: BLOCKED },
Relays: { text: formatMessage(messages.Relays), value: RELAYS },
Bookmarks: { text: formatMessage(messages.Bookmarks), value: BOOKMARKS },
};
const [tab, setTab] = useState(ProfileTab.Notes);
const optionalTabs = [ProfileTab.Zaps, ProfileTab.Relays, ProfileTab.Bookmarks, ProfileTab.Muted].filter(a =>
unwrap(a)
) as Tab[];
const horizontalScroll = useHorizontalScroll();
useEffect(() => {
if (params.id?.match(EmailRegex)) {
getNip05PubKey(params.id).then(a => {
setId(a);
});
} else {
const nav = parseNostrLink(params.id ?? "");
if (nav?.type === NostrPrefix.PublicKey || nav?.type === NostrPrefix.Profile) {
// todo: use relays if any for nprofile
setId(nav.id);
} else {
setId(parseId(params.id ?? ""));
}
}
setTab(ProfileTab.Notes);
}, [params]);
function username() {
return (
{user?.display_name || user?.name || "Nostrich"}
{user?.nip05 && }
{links()}
);
}
function links() {
return (
{user?.website && (
)}
{lnurl && (
setShowLnQr(true)}>
{lnurl}
)}
setShowLnQr(false)}
author={id}
target={user?.display_name || user?.name}
/>
);
}
function bio() {
return (
aboutText.length > 0 && (
{about}
)
);
}
function tabContent() {
if (!id) return null;
switch (tab.value) {
case NOTES:
return (
<>
{pinned
.filter(a => a.kind === EventKind.TextNote)
.map(n => {
return (
);
})}
>
);
case ZAPS: {
return ;
}
case FOLLOWS: {
if (isMe) {
return ;
} else {
return ;
}
}
case FOLLOWERS: {
return ;
}
case MUTED: {
return ;
}
case BLOCKED: {
return ;
}
case RELAYS: {
return ;
}
case BOOKMARKS: {
return ;
}
}
}
function avatar() {
return (
);
}
function renderIcons() {
if (!id) return;
const link = encodeTLV(id, NostrPrefix.Profile);
return (
setShowProfileQr(true)}>
{showProfileQr && (
setShowProfileQr(false)}>
)}
{isMe ? (
<>
>
) : (
<>
{lnurl && (
setShowLnQr(true)}>
)}
{loginPubKey && (
<>
navigate(`/messages/${hexToBech32(NostrPrefix.PublicKey, id)}`)}>
>
)}
>
)}
);
}
function userDetails() {
if (!id) return;
return (
{username()}
{renderIcons()}
{!isMe && }
{bio()}
);
}
function renderTab(v: Tab) {
return ;
}
const w = window.document.querySelector(".page")?.clientWidth;
return (
<>
{user?.banner &&
}
{avatar()}
{userDetails()}
{[ProfileTab.Notes, ProfileTab.Followers, ProfileTab.Follows].map(renderTab)}
{optionalTabs.map(renderTab)}
{isMe && blocked.length > 0 && renderTab(ProfileTab.Blocked)}
{tabContent()}
>
);
}