feat: display banner in profile

This commit is contained in:
Alejandro Gomez
2023-01-13 23:48:24 +01:00
parent b43f01ff4a
commit 7c6483b991
3 changed files with 106 additions and 63 deletions

View File

@ -8,7 +8,7 @@ export default function FollowButton(props) {
const publiser = useEventPublisher(); const publiser = useEventPublisher();
const follows = useSelector(s => s.login.follows); const follows = useSelector(s => s.login.follows);
let isFollowing = follows?.includes(pubkey) ?? false; let isFollowing = follows?.includes(pubkey) ?? false;
const baseClassName = isFollowing ? `btn btn-warn` : `btn btn-success` const baseClassName = isFollowing ? `btn btn-warn follow-button` : `btn btn-success follow-button`
const className = props.className ? `${baseClassName} ${props.className}` : `${baseClassName}`; const className = props.className ? `${baseClassName} ${props.className}` : `${baseClassName}`;
async function follow(pubkey) { async function follow(pubkey) {

View File

@ -1,9 +1,24 @@
.profile { .profile {
align-items: flex-start; flex-direction: column;
} }
.profile > div:last-child { .profile .banner {
margin-left: 10px; width: 100%;
height: 210px;
margin-bottom: -110px;
object-fit: cover;
mask-image: linear-gradient(to bottom, var(--bg-color), rgba(0,0,0,0));
-webkit-mask-image: linear-gradient(to bottom, var(--bg-color), rgba(0,0,0,0));
z-index: 0;
}
@media (min-width: 720px) {
.profile .banner {
width: 100%;
max-width: 720px;
height: 300px;
margin-bottom: -120px;
}
} }
.profile p { .profile p {
@ -14,14 +29,17 @@
margin: 0; margin: 0;
} }
.profile .avatar-wrapper { .profile .avatar-wrapper {
margin: auto 10px; align-self: flex-start;
z-index: 1;
margin-left: 4px;
} }
.profile .avatar { .profile .avatar {
border-radius: 50%; border-radius: 50%;
height: 256px; height: 210px;
width: 256px; width: 210px;
background-image: var(--img-url), var(--gray-gradient); background-image: var(--img-url), var(--gray-gradient);
border: 4px solid transparent; border: 4px solid transparent;
background-origin: border-box; background-origin: border-box;
@ -38,23 +56,40 @@
background-image: var(--img-url), var(--nostrplebs-gradient); background-image: var(--img-url), var(--nostrplebs-gradient);
} }
.profile .name {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.profile .name h2 {
margin: 0;
}
.profile .details { .profile .details {
margin-top: auto; max-width: 680px;
margin-bottom: auto; width: 100%;
overflow: hidden; }
.profile .details p {
word-break: break-word;
}
.profile .details a {
color: var(--highlight);
} }
.profile .website { .profile .website {
padding-left: 0;
color: var(--highlight); color: var(--highlight);
margin-bottom: 2px; margin-bottom: 4px;
} }
.profile .lnurl { .profile .lnurl {
padding-left: 0; color: var(--highlight);
} }
.profile .btn-icon { .profile .btn-icon {
color: var(--font-color);
padding: 6px; padding: 6px;
margin-left: 4px; margin-left: 4px;
} }
@ -64,8 +99,9 @@
font-size: 10px; font-size: 10px;
} }
.profile a { .profile .lnurl {
color: var(--highlight); overflow: hidden;
text-overflow: ellipsis;
} }
.profile .lnurl::before { .profile .lnurl::before {
@ -73,22 +109,31 @@
font-size: 10px; font-size: 10px;
} }
@media(max-width: 720px) { .profile .details-wrapper {
.profile { display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: flex-start;
} justify-content: space-between;
.profile > div:last-child { position: relative;
margin: 5px 0;
width: 100%; width: 100%;
} margin-left: 4px;
} }
@media(max-width: 360px) { .profile .copy .body { font-size: 12px }
.profile .name { flex-direction: column; }
.profile .name .btn { @media (min-width: 360px) {
margin-top: 5px; .profile .copy .body { font-size: 14px }
.profile .details-wrapper, .profile .avatar-wrapper { margin-left: 21px; }
} }
@media (min-width: 720px) {
.profile .details-wrapper, .profile .avatar-wrapper { margin-left: 30px; }
}
.profile .follow-button {
position: absolute;
top: -30px;
right: 20px;
} }
.tabs { .tabs {

View File

@ -45,35 +45,20 @@ export default function ProfilePage() {
setTab(ProfileTab.Notes); setTab(ProfileTab.Notes);
}, [params]); }, [params]);
function details() { function username() {
const lnurl = extractLnAddress(user?.lud16 || user?.lud06 || "");
return ( return (
<> <div className="name">
<div className="flex name"> <h2>{user?.display_name || user?.name}</h2>
<div className="f-grow f-ellipsis">
<h2>{user?.display_name || user?.name}</h2></div>
<div className="flex">
{isMe ? (
<div className="btn btn-icon" onClick={() => navigate("/settings")}>
<FontAwesomeIcon icon={faGear} size="lg" />
</div>
) : <>
<div className="btn mr5" onClick={() => navigate(`/messages/${hexToBech32("npub", id)}`)}>
<FontAwesomeIcon icon={faEnvelope} size="lg" />
</div>
<FollowButton pubkey={id} />
</>
}
</div>
</div>
<div className="flex">
<div className="f-grow">
<Copy text={params.id} /> <Copy text={params.id} />
{user?.nip05 && <Nip05 name={name} domain={domain} isVerified={isVerified} couldNotVerify={couldNotVerify} />} {user?.nip05 && <Nip05 name={name} domain={domain} isVerified={isVerified} couldNotVerify={couldNotVerify} />}
</div> </div>
)
}
</div> function details() {
const lnurl = extractLnAddress(user?.lud16 || user?.lud06 || "");
return (
<div className="details">
<p>{about}</p> <p>{about}</p>
{user?.website && ( {user?.website && (
@ -89,7 +74,7 @@ export default function ProfilePage() {
</div> </div>
</div> : null} </div> : null}
<LNURLTip svc={lnurl} show={showLnQr} onClose={() => setShowLnQr(false)} /> <LNURLTip svc={lnurl} show={showLnQr} onClose={() => setShowLnQr(false)} />
</> </div>
) )
} }
@ -118,11 +103,24 @@ export default function ProfilePage() {
return ( return (
<> <>
<div className="profile flex"> <div className="profile flex">
<img className="banner" src={user?.banner ? user.banner : avatarUrl} />
<div className="avatar-wrapper"> <div className="avatar-wrapper">
<div style={{ '--img-url': backgroundImage }} className="avatar" data-domain={isVerified ? domain : ''}> <div style={{ '--img-url': backgroundImage }} className="avatar" data-domain={isVerified ? domain : ''}>
</div> </div>
</div> </div>
<div className="f-grow details"> <div className="details-wrapper">
{username()}
{isMe ? (
<div className="btn btn-icon follow-button" onClick={() => navigate("/settings")}>
<FontAwesomeIcon icon={faGear} size="lg" />
</div>
) : <>
<div className="btn mr5" onClick={() => navigate(`/messages/${hexToBech32("npub", id)}`)}>
<FontAwesomeIcon icon={faEnvelope} size="lg" />
</div>
<FollowButton pubkey={id} />
</>
}
{details()} {details()}
</div> </div>
</div> </div>