diff --git a/packages/app/src/Feed/BookmarkFeed.tsx b/packages/app/src/Feed/BookmarkFeed.tsx index aea7617..3e25f9f 100644 --- a/packages/app/src/Feed/BookmarkFeed.tsx +++ b/packages/app/src/Feed/BookmarkFeed.tsx @@ -4,7 +4,7 @@ import { RootState } from "State/Store"; import { HexKey, Lists } from "@snort/nostr"; import useNotelistSubscription from "Feed/useNotelistSubscription"; -export default function useBookmarkFeed(pubkey: HexKey) { +export default function useBookmarkFeed(pubkey?: HexKey) { const { bookmarked } = useSelector((s: RootState) => s.login); return useNotelistSubscription(pubkey, Lists.Bookmarked, bookmarked); } diff --git a/packages/app/src/Feed/FollowersFeed.ts b/packages/app/src/Feed/FollowersFeed.ts index f5efa5a..4c375e0 100644 --- a/packages/app/src/Feed/FollowersFeed.ts +++ b/packages/app/src/Feed/FollowersFeed.ts @@ -3,8 +3,9 @@ import { HexKey } from "@snort/nostr"; import { EventKind, Subscriptions } from "@snort/nostr"; import useSubscription from "Feed/Subscription"; -export default function useFollowersFeed(pubkey: HexKey) { +export default function useFollowersFeed(pubkey?: HexKey) { const sub = useMemo(() => { + if (!pubkey) return null; const x = new Subscriptions(); x.Id = `followers:${pubkey.slice(0, 12)}`; x.Kinds = new Set([EventKind.ContactList]); diff --git a/packages/app/src/Feed/FollowsFeed.ts b/packages/app/src/Feed/FollowsFeed.ts index 0073464..626b25f 100644 --- a/packages/app/src/Feed/FollowsFeed.ts +++ b/packages/app/src/Feed/FollowsFeed.ts @@ -5,12 +5,12 @@ import { HexKey, TaggedRawEvent, EventKind, Subscriptions } from "@snort/nostr"; import useSubscription from "Feed/Subscription"; import { RootState } from "State/Store"; -export default function useFollowsFeed(pubkey: HexKey) { +export default function useFollowsFeed(pubkey?: HexKey) { const { publicKey, follows } = useSelector((s: RootState) => s.login); const isMe = publicKey === pubkey; const sub = useMemo(() => { - if (isMe) return null; + if (isMe || !pubkey) return null; const x = new Subscriptions(); x.Id = `follows:${pubkey.slice(0, 12)}`; x.Kinds = new Set([EventKind.ContactList]); @@ -23,11 +23,12 @@ export default function useFollowsFeed(pubkey: HexKey) { if (isMe) { return follows; } + return getFollowing(contactFeed.store.notes ?? [], pubkey); - }, [contactFeed.store, follows]); + }, [contactFeed.store, follows, pubkey]); } -export function getFollowing(notes: TaggedRawEvent[], pubkey: HexKey) { +export function getFollowing(notes: TaggedRawEvent[], pubkey?: HexKey) { const contactLists = notes.filter(a => a.kind === EventKind.ContactList && a.pubkey === pubkey); const pTags = contactLists?.map(a => a.tags.filter(b => b[0] === "p").map(c => c[1])); return [...new Set(pTags?.flat())]; diff --git a/packages/app/src/Feed/MuteList.ts b/packages/app/src/Feed/MuteList.ts index ebcb5c8..918acaa 100644 --- a/packages/app/src/Feed/MuteList.ts +++ b/packages/app/src/Feed/MuteList.ts @@ -7,12 +7,12 @@ import { EventKind, Subscriptions } from "@snort/nostr"; import useSubscription, { NoteStore } from "Feed/Subscription"; import { RootState } from "State/Store"; -export default function useMutedFeed(pubkey: HexKey) { +export default function useMutedFeed(pubkey?: HexKey) { const { publicKey, muted } = useSelector((s: RootState) => s.login); const isMe = publicKey === pubkey; const sub = useMemo(() => { - if (isMe) return null; + if (isMe || !pubkey) return null; const sub = new Subscriptions(); sub.Id = `muted:${pubkey.slice(0, 12)}`; sub.Kinds = new Set([EventKind.PubkeyLists]); @@ -25,8 +25,11 @@ export default function useMutedFeed(pubkey: HexKey) { const mutedFeed = useSubscription(sub, { leaveOpen: false, cache: true }); const mutedList = useMemo(() => { - return getMuted(mutedFeed.store, pubkey); - }, [mutedFeed.store]); + if (pubkey) { + return getMuted(mutedFeed.store, pubkey); + } + return []; + }, [mutedFeed.store, pubkey]); return isMe ? muted : mutedList; } diff --git a/packages/app/src/Feed/PinnedFeed.tsx b/packages/app/src/Feed/PinnedFeed.tsx index 2932b34..79137c4 100644 --- a/packages/app/src/Feed/PinnedFeed.tsx +++ b/packages/app/src/Feed/PinnedFeed.tsx @@ -4,7 +4,7 @@ import { RootState } from "State/Store"; import { HexKey, Lists } from "@snort/nostr"; import useNotelistSubscription from "Feed/useNotelistSubscription"; -export default function usePinnedFeed(pubkey: HexKey) { +export default function usePinnedFeed(pubkey?: HexKey) { const { pinned } = useSelector((s: RootState) => s.login); return useNotelistSubscription(pubkey, Lists.Pinned, pinned); } diff --git a/packages/app/src/Feed/RelaysFeed.tsx b/packages/app/src/Feed/RelaysFeed.tsx index 26171c8..b5f7605 100644 --- a/packages/app/src/Feed/RelaysFeed.tsx +++ b/packages/app/src/Feed/RelaysFeed.tsx @@ -3,8 +3,9 @@ import { HexKey, FullRelaySettings } from "@snort/nostr"; import { EventKind, Subscriptions } from "@snort/nostr"; import useSubscription from "./Subscription"; -export default function useRelaysFeed(pubkey: HexKey) { +export default function useRelaysFeed(pubkey?: HexKey) { const sub = useMemo(() => { + if (!pubkey) return null; const x = new Subscriptions(); x.Id = `relays:${pubkey.slice(0, 12)}`; x.Kinds = new Set([EventKind.ContactList]); diff --git a/packages/app/src/Feed/ZapsFeed.ts b/packages/app/src/Feed/ZapsFeed.ts index a19ccfb..1ff399b 100644 --- a/packages/app/src/Feed/ZapsFeed.ts +++ b/packages/app/src/Feed/ZapsFeed.ts @@ -3,8 +3,9 @@ import { HexKey, EventKind, Subscriptions } from "@snort/nostr"; import { parseZap } from "Element/Zap"; import useSubscription from "./Subscription"; -export default function useZapsFeed(pubkey: HexKey) { +export default function useZapsFeed(pubkey?: HexKey) { const sub = useMemo(() => { + if (!pubkey) return null; const x = new Subscriptions(); x.Id = `zaps:${pubkey.slice(0, 12)}`; x.Kinds = new Set([EventKind.ZapReceipt]); diff --git a/packages/app/src/Feed/useNotelistSubscription.ts b/packages/app/src/Feed/useNotelistSubscription.ts index db13b54..f300ce4 100644 --- a/packages/app/src/Feed/useNotelistSubscription.ts +++ b/packages/app/src/Feed/useNotelistSubscription.ts @@ -6,12 +6,12 @@ import { HexKey, Lists, EventKind, Subscriptions } from "@snort/nostr"; import useSubscription from "Feed/Subscription"; import { RootState } from "State/Store"; -export default function useNotelistSubscription(pubkey: HexKey, l: Lists, defaultIds: HexKey[]) { +export default function useNotelistSubscription(pubkey: HexKey | undefined, l: Lists, defaultIds: HexKey[]) { const { preferences, publicKey } = useSelector((s: RootState) => s.login); const isMe = publicKey === pubkey; const sub = useMemo(() => { - if (isMe) return null; + if (isMe || !pubkey) return null; const sub = new Subscriptions(); sub.Id = `note-list-${l}:${pubkey.slice(0, 12)}`; sub.Kinds = new Set([EventKind.NoteLists]); @@ -33,12 +33,13 @@ export default function useNotelistSubscription(pubkey: HexKey, l: Lists, defaul }, [store.notes, isMe, defaultIds]); const esub = useMemo(() => { + if (!pubkey) return null; const s = new Subscriptions(); s.Id = `${l}-notes:${pubkey.slice(0, 12)}`; s.Kinds = new Set([EventKind.TextNote]); s.Ids = new Set(etags); return s; - }, [etags]); + }, [etags, pubkey]); const subRelated = useMemo(() => { let sub: Subscriptions | undefined; diff --git a/packages/app/src/Pages/Login.tsx b/packages/app/src/Pages/Login.tsx index cac6974..bc2548a 100644 --- a/packages/app/src/Pages/Login.tsx +++ b/packages/app/src/Pages/Login.tsx @@ -46,6 +46,19 @@ const Artwork: Array = [ }, ]; +export async function getNip05PubKey(addr: string): Promise { + const [username, domain] = addr.split("@"); + const rsp = await fetch(`https://${domain}/.well-known/nostr.json?name=${encodeURIComponent(username)}`); + if (rsp.ok) { + const data = await rsp.json(); + const pKey = data.names[username]; + if (pKey) { + return pKey; + } + } + throw new Error("User key not found"); +} + export default function LoginPage() { const dispatch = useDispatch(); const navigate = useNavigate(); @@ -69,19 +82,6 @@ export default function LoginPage() { setArt(ret); }, []); - async function getNip05PubKey(addr: string) { - const [username, domain] = addr.split("@"); - const rsp = await fetch(`https://${domain}/.well-known/nostr.json?name=${encodeURIComponent(username)}`); - if (rsp.ok) { - const data = await rsp.json(); - const pKey = data.names[username]; - if (pKey) { - return pKey; - } - } - throw new Error("User key not found"); - } - async function doLogin() { try { if (key.startsWith("nsec")) { diff --git a/packages/app/src/Pages/ProfilePage.tsx b/packages/app/src/Pages/ProfilePage.tsx index 0a9d890..4eb54d8 100644 --- a/packages/app/src/Pages/ProfilePage.tsx +++ b/packages/app/src/Pages/ProfilePage.tsx @@ -1,8 +1,9 @@ import "./ProfilePage.css"; -import { useEffect, useMemo, useState, CSSProperties } from "react"; +import { useEffect, useState } from "react"; import { useIntl, FormattedMessage } from "react-intl"; import { useSelector } from "react-redux"; import { useNavigate, useParams } from "react-router-dom"; +import { NostrPrefix } from "@snort/nostr"; import { unwrap } from "Util"; import { formatShort } from "Number"; @@ -32,20 +33,20 @@ import Text from "Element/Text"; import SendSats from "Element/SendSats"; import Nip05 from "Element/Nip05"; import Copy from "Element/Copy"; -import ProfilePreview from "Element/ProfilePreview"; 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 { HexKey, NostrPrefix } from "@snort/nostr"; import FollowsYou from "Element/FollowsYou"; import QrCode from "Element/QrCode"; import Modal from "Element/Modal"; 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; @@ -61,10 +62,9 @@ export default function ProfilePage() { const { formatMessage } = useIntl(); const params = useParams(); const navigate = useNavigate(); - const id = useMemo(() => parseId(params.id ?? ""), [params]); + const [id, setId] = useState(); const user = useUserProfile(id); - const loggedOut = useSelector(s => s.login.loggedOut); - const loginPubKey = useSelector(s => s.login.publicKey); + const loginPubKey = useSelector((s: RootState) => s.login.publicKey); const isMe = loginPubKey === id; const [showLnQr, setShowLnQr] = useState(false); const [showProfileQr, setShowProfileQr] = useState(false); @@ -75,7 +75,7 @@ export default function ProfilePage() { users: new Map(), creator: "", }); - const npub = !id.startsWith("npub") ? hexToBech32("npub", id || undefined) : id; + const npub = !id?.startsWith("npub") ? hexToBech32("npub", id || undefined) : id; const lnurl = extractLnAddress(user?.lud16 || user?.lud06 || ""); const website_url = @@ -112,6 +112,13 @@ export default function ProfilePage() { const horizontalScroll = useHorizontalScroll(); useEffect(() => { + if (params.id?.match(EmailRegex)) { + getNip05PubKey(params.id).then(a => { + setId(a); + }); + } else { + setId(parseId(params.id ?? "")); + } setTab(ProfileTab.Notes); }, [params]); @@ -174,6 +181,8 @@ export default function ProfilePage() { } function tabContent() { + if (!id) return null; + switch (tab.value) { case NOTES: return ( @@ -254,7 +263,7 @@ export default function ProfilePage() { {showProfileQr && ( setShowProfileQr(false)}> - + )} - {!loggedOut && ( + {loginPubKey && ( <> navigate(`/messages/${hexToBech32(NostrPrefix.PublicKey, id)}`)}> @@ -294,7 +303,7 @@ export default function ProfilePage() { {username()}
{renderIcons()} - {!isMe && } + {!isMe && }
{bio()} @@ -306,7 +315,6 @@ export default function ProfilePage() { } const w = window.document.querySelector(".page")?.clientWidth; - const bannerStyle = user?.banner ? ({ "--img-url": `url(${user.banner})` } as CSSProperties) : {}; return ( <>