bug: use page width for banner
This commit is contained in:
parent
08acab4831
commit
14769f8f33
@ -2,13 +2,13 @@ import useImgProxy from "Feed/ImgProxy";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export const ProxyImg = (props: any) => {
|
export const ProxyImg = (props: any) => {
|
||||||
const { src, ...rest } = props;
|
const { src, size, ...rest } = props;
|
||||||
const [url, setUrl] = useState<string>();
|
const [url, setUrl] = useState<string>();
|
||||||
const { proxy } = useImgProxy();
|
const { proxy } = useImgProxy();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (src) {
|
if (src) {
|
||||||
proxy(src)
|
proxy(src, size)
|
||||||
.then(a => setUrl(a))
|
.then(a => setUrl(a))
|
||||||
.catch(console.warn);
|
.catch(console.warn);
|
||||||
}
|
}
|
||||||
|
@ -32,111 +32,111 @@ import Modal from "Element/Modal";
|
|||||||
import { ProxyImg } from "Element/ProxyImg"
|
import { ProxyImg } from "Element/ProxyImg"
|
||||||
|
|
||||||
enum ProfileTab {
|
enum ProfileTab {
|
||||||
Notes = "Notes",
|
Notes = "Notes",
|
||||||
Reactions = "Reactions",
|
Reactions = "Reactions",
|
||||||
Followers = "Followers",
|
Followers = "Followers",
|
||||||
Follows = "Follows",
|
Follows = "Follows",
|
||||||
Muted = "Muted",
|
Muted = "Muted",
|
||||||
Blocked = "Blocked"
|
Blocked = "Blocked"
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ProfilePage() {
|
export default function ProfilePage() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const id = useMemo(() => parseId(params.id!), [params]);
|
const id = useMemo(() => parseId(params.id!), [params]);
|
||||||
const user = useUserProfile(id);
|
const user = useUserProfile(id);
|
||||||
const loggedOut = useSelector<RootState, boolean | undefined>(s => s.login.loggedOut);
|
const loggedOut = useSelector<RootState, boolean | undefined>(s => s.login.loggedOut);
|
||||||
const loginPubKey = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
|
const loginPubKey = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
|
||||||
const follows = useSelector<RootState, HexKey[]>(s => s.login.follows);
|
const follows = useSelector<RootState, HexKey[]>(s => s.login.follows);
|
||||||
const isMe = loginPubKey === id;
|
const isMe = loginPubKey === id;
|
||||||
const [showLnQr, setShowLnQr] = useState<boolean>(false);
|
const [showLnQr, setShowLnQr] = useState<boolean>(false);
|
||||||
const [tab, setTab] = useState(ProfileTab.Notes);
|
const [tab, setTab] = useState(ProfileTab.Notes);
|
||||||
const [showProfileQr, setShowProfileQr] = useState<boolean>(false);
|
const [showProfileQr, setShowProfileQr] = useState<boolean>(false);
|
||||||
const aboutText = user?.about || ''
|
const aboutText = user?.about || ''
|
||||||
const about = Text({ content: aboutText, tags: [], users: new Map() })
|
const about = Text({ content: aboutText, tags: [], users: new Map() })
|
||||||
const lnurl = extractLnAddress(user?.lud16 || user?.lud06 || "");
|
const lnurl = extractLnAddress(user?.lud16 || user?.lud06 || "");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTab(ProfileTab.Notes);
|
setTab(ProfileTab.Notes);
|
||||||
}, [params]);
|
}, [params]);
|
||||||
|
|
||||||
function username() {
|
function username() {
|
||||||
return (
|
return (
|
||||||
<div className="name">
|
<div className="name">
|
||||||
<h2>
|
<h2>
|
||||||
{user?.display_name || user?.name || 'Nostrich'}
|
{user?.display_name || user?.name || 'Nostrich'}
|
||||||
<FollowsYou pubkey={id} />
|
<FollowsYou pubkey={id} />
|
||||||
</h2>
|
</h2>
|
||||||
{user?.nip05 && <Nip05 nip05={user.nip05} pubkey={user.pubkey} />}
|
{user?.nip05 && <Nip05 nip05={user.nip05} pubkey={user.pubkey} />}
|
||||||
<Copy text={params.id || ""} />
|
<Copy text={params.id || ""} />
|
||||||
{links()}
|
{links()}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function links() {
|
||||||
|
return (
|
||||||
|
<div className="links">
|
||||||
|
{user?.website && (
|
||||||
|
<div className="website f-ellipsis">
|
||||||
|
<span className="link-icon">
|
||||||
|
<Link />
|
||||||
|
</span>
|
||||||
|
<a href={user.website} target="_blank" rel="noreferrer">{user.website}</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<LNURLTip svc={lnurl} show={showLnQr} onClose={() => setShowLnQr(false)} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function bio() {
|
||||||
|
return aboutText.length > 0 && (
|
||||||
|
<>
|
||||||
|
<h3>Bio</h3>
|
||||||
|
<div className="details">
|
||||||
|
{about}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function tabContent() {
|
||||||
|
switch (tab) {
|
||||||
|
case ProfileTab.Notes:
|
||||||
|
return <Timeline key={id} subject={{ type: "pubkey", items: [id] }} postsOnly={false} method={"LIMIT_UNTIL"} ignoreModeration={true} />;
|
||||||
|
case ProfileTab.Follows: {
|
||||||
|
if (isMe) {
|
||||||
|
return (
|
||||||
|
<div className="main-content">
|
||||||
|
<h4>Following {follows.length}</h4>
|
||||||
|
{follows.map(a => <ProfilePreview key={a} pubkey={a.toLowerCase()} options={{ about: false }} />)}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
} else {
|
||||||
|
return <FollowsList pubkey={id} />;
|
||||||
function links() {
|
|
||||||
return (
|
|
||||||
<div className="links">
|
|
||||||
{user?.website && (
|
|
||||||
<div className="website f-ellipsis">
|
|
||||||
<span className="link-icon">
|
|
||||||
<Link />
|
|
||||||
</span>
|
|
||||||
<a href={user.website} target="_blank" rel="noreferrer">{user.website}</a>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<LNURLTip svc={lnurl} show={showLnQr} onClose={() => setShowLnQr(false)} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function bio() {
|
|
||||||
return aboutText.length > 0 && (
|
|
||||||
<>
|
|
||||||
<h3>Bio</h3>
|
|
||||||
<div className="details">
|
|
||||||
{about}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function tabContent() {
|
|
||||||
switch (tab) {
|
|
||||||
case ProfileTab.Notes:
|
|
||||||
return <Timeline key={id} subject={{ type: "pubkey", items: [id] }} postsOnly={false} method={"LIMIT_UNTIL"} ignoreModeration={true} />;
|
|
||||||
case ProfileTab.Follows: {
|
|
||||||
if (isMe) {
|
|
||||||
return (
|
|
||||||
<div className="main-content">
|
|
||||||
<h4>Following {follows.length}</h4>
|
|
||||||
{follows.map(a => <ProfilePreview key={a} pubkey={a.toLowerCase()} options={{ about: false }} />)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return <FollowsList pubkey={id} />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case ProfileTab.Followers: {
|
|
||||||
return <FollowersList pubkey={id} />
|
|
||||||
}
|
|
||||||
case ProfileTab.Muted: {
|
|
||||||
return isMe ? <BlockList variant="muted" /> : <MutedList pubkey={id} />
|
|
||||||
}
|
|
||||||
case ProfileTab.Blocked: {
|
|
||||||
return isMe ? <BlockList variant="blocked" /> : null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
case ProfileTab.Followers: {
|
||||||
|
return <FollowersList pubkey={id} />
|
||||||
|
}
|
||||||
|
case ProfileTab.Muted: {
|
||||||
|
return isMe ? <BlockList variant="muted" /> : <MutedList pubkey={id} />
|
||||||
|
}
|
||||||
|
case ProfileTab.Blocked: {
|
||||||
|
return isMe ? <BlockList variant="blocked" /> : null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function avatar() {
|
function avatar() {
|
||||||
return (
|
return (
|
||||||
<div className="avatar-wrapper">
|
<div className="avatar-wrapper">
|
||||||
<Avatar user={user} />
|
<Avatar user={user} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderIcons() {
|
function renderIcons() {
|
||||||
return (
|
return (
|
||||||
@ -146,7 +146,7 @@ export default function ProfilePage() {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
{showProfileQr && (
|
{showProfileQr && (
|
||||||
<Modal className="qr-modal" onClose={() => setShowProfileQr(false)}>
|
<Modal className="qr-modal" onClose={() => setShowProfileQr(false)}>
|
||||||
<QrCode data={`nostr:${hexToBech32("npub", id)}`} link={undefined} className="m10"/>
|
<QrCode data={`nostr:${hexToBech32("npub", id)}`} link={undefined} className="m10" />
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
{isMe ? (
|
{isMe ? (
|
||||||
@ -164,7 +164,7 @@ export default function ProfilePage() {
|
|||||||
{!loggedOut && (
|
{!loggedOut && (
|
||||||
<>
|
<>
|
||||||
<IconButton onClick={() => navigate(`/messages/${hexToBech32("npub", id)}`)}>
|
<IconButton onClick={() => navigate(`/messages/${hexToBech32("npub", id)}`)}>
|
||||||
<Envelope width={16} height={13} />
|
<Envelope width={16} height={13} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -174,37 +174,38 @@ export default function ProfilePage() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function userDetails() {
|
function userDetails() {
|
||||||
return (
|
|
||||||
<div className="details-wrapper">
|
|
||||||
{username()}
|
|
||||||
<div className="profile-actions">
|
|
||||||
{renderIcons()}
|
|
||||||
{!isMe && <FollowButton pubkey={id} />}
|
|
||||||
</div>
|
|
||||||
{bio()}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderTab(v: ProfileTab) {
|
|
||||||
return <div className={`tab f-1${tab === v ? " active" : ""}`} key={v} onClick={() => setTab(v)}>{v}</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="details-wrapper">
|
||||||
<div className="profile flex">
|
{username()}
|
||||||
{user?.banner && <ProxyImg alt="banner" className="banner" src={user.banner} />}
|
<div className="profile-actions">
|
||||||
<div className="profile-wrapper flex">
|
{renderIcons()}
|
||||||
{avatar()}
|
{!isMe && <FollowButton pubkey={id} />}
|
||||||
{userDetails()}
|
</div>
|
||||||
</div>
|
{bio()}
|
||||||
</div>
|
</div>
|
||||||
<div className="tabs">
|
|
||||||
{[ProfileTab.Notes, ProfileTab.Followers, ProfileTab.Follows, ProfileTab.Muted].map(renderTab)}
|
|
||||||
{isMe && renderTab(ProfileTab.Blocked)}
|
|
||||||
</div>
|
|
||||||
{tabContent()}
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTab(v: ProfileTab) {
|
||||||
|
return <div className={`tab f-1${tab === v ? " active" : ""}`} key={v} onClick={() => setTab(v)}>{v}</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
const w = window.document.querySelector(".page")?.clientWidth;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="profile flex">
|
||||||
|
{user?.banner && <ProxyImg alt="banner" className="banner" src={user.banner} size={w}/>}
|
||||||
|
<div className="profile-wrapper flex">
|
||||||
|
{avatar()}
|
||||||
|
{userDetails()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="tabs">
|
||||||
|
{[ProfileTab.Notes, ProfileTab.Followers, ProfileTab.Follows, ProfileTab.Muted].map(renderTab)}
|
||||||
|
{isMe && renderTab(ProfileTab.Blocked)}
|
||||||
|
</div>
|
||||||
|
{tabContent()}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user