qr on profile
This commit is contained in:
parent
1d29d53c7b
commit
5def7c8b9a
22
src/Element/IconButton.tsx
Normal file
22
src/Element/IconButton.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
interface IconButtonProps {
|
||||
onClick(): void
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const IconButton = ({ onClick, children }: IconButtonProps) => {
|
||||
return (
|
||||
<button
|
||||
className="icon"
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="icon-wrapper">
|
||||
{children}
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconButton
|
@ -6,7 +6,8 @@ export interface QrCodeProps {
|
||||
link?: string,
|
||||
avatar?: string,
|
||||
height?: number,
|
||||
width?: number
|
||||
width?: number,
|
||||
className?: string
|
||||
}
|
||||
|
||||
export default function QrCode(props: QrCodeProps) {
|
||||
@ -46,6 +47,6 @@ export default function QrCode(props: QrCodeProps) {
|
||||
}, [props.data, props.link]);
|
||||
|
||||
return (
|
||||
<div className="qr" ref={qrRef}></div>
|
||||
<div className={`qr${props.className ? ` ${props.className}` : ""}`} ref={qrRef}></div>
|
||||
);
|
||||
}
|
11
src/Icons/Qr.tsx
Normal file
11
src/Icons/Qr.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import IconProps from './IconProps';
|
||||
|
||||
const Qr = (props: IconProps) => {
|
||||
return (
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path d="M4.5 4.5H4.51M15.5 4.5H15.51M4.5 15.5H4.51M11 11H11.01M15.5 15.5H15.51M15 19H19V15M12 14.5V19M19 12H14.5M13.6 8H17.4C17.9601 8 18.2401 8 18.454 7.89101C18.6422 7.79513 18.7951 7.64215 18.891 7.45399C19 7.24008 19 6.96005 19 6.4V2.6C19 2.03995 19 1.75992 18.891 1.54601C18.7951 1.35785 18.6422 1.20487 18.454 1.10899C18.2401 1 17.9601 1 17.4 1H13.6C13.0399 1 12.7599 1 12.546 1.10899C12.3578 1.20487 12.2049 1.35785 12.109 1.54601C12 1.75992 12 2.03995 12 2.6V6.4C12 6.96005 12 7.24008 12.109 7.45399C12.2049 7.64215 12.3578 7.79513 12.546 7.89101C12.7599 8 13.0399 8 13.6 8ZM2.6 8H6.4C6.96005 8 7.24008 8 7.45399 7.89101C7.64215 7.79513 7.79513 7.64215 7.89101 7.45399C8 7.24008 8 6.96005 8 6.4V2.6C8 2.03995 8 1.75992 7.89101 1.54601C7.79513 1.35785 7.64215 1.20487 7.45399 1.10899C7.24008 1 6.96005 1 6.4 1H2.6C2.03995 1 1.75992 1 1.54601 1.10899C1.35785 1.20487 1.20487 1.35785 1.10899 1.54601C1 1.75992 1 2.03995 1 2.6V6.4C1 6.96005 1 7.24008 1.10899 7.45399C1.20487 7.64215 1.35785 7.79513 1.54601 7.89101C1.75992 8 2.03995 8 2.6 8ZM2.6 19H6.4C6.96005 19 7.24008 19 7.45399 18.891C7.64215 18.7951 7.79513 18.6422 7.89101 18.454C8 18.2401 8 17.9601 8 17.4V13.6C8 13.0399 8 12.7599 7.89101 12.546C7.79513 12.3578 7.64215 12.2049 7.45399 12.109C7.24008 12 6.96005 12 6.4 12H2.6C2.03995 12 1.75992 12 1.54601 12.109C1.35785 12.2049 1.20487 12.3578 1.10899 12.546C1 12.7599 1 13.0399 1 13.6V17.4C1 17.9601 1 18.2401 1.10899 18.454C1.20487 18.6422 1.35785 18.7951 1.54601 18.891C1.75992 19 2.03995 19 2.6 19Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default Qr
|
@ -1,7 +1,7 @@
|
||||
const Search = () => {
|
||||
return (
|
||||
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19 19.5L14.65 15.15M17 9.5C17 13.9183 13.4183 17.5 9 17.5C4.58172 17.5 1 13.9183 1 9.5C1 5.08172 4.58172 1.5 9 1.5C13.4183 1.5 17 5.08172 17 9.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M19 19.5L14.65 15.15M17 9.5C17 13.9183 13.4183 17.5 9 17.5C4.58172 17.5 1 13.9183 1 9.5C1 5.08172 4.58172 1.5 9 1.5C13.4183 1.5 17 5.08172 17 9.5Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
@ -46,10 +46,6 @@
|
||||
color: var(--gray-light);
|
||||
}
|
||||
|
||||
.profile .name .copy {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.profile .avatar-wrapper {
|
||||
z-index: 1;
|
||||
}
|
||||
@ -103,10 +99,6 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tabs > div {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.profile .links {
|
||||
margin-top: 4px;
|
||||
margin-left: 2px;
|
||||
@ -175,6 +167,15 @@
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.profile .icon-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media (min-width: 520px) {
|
||||
@ -187,6 +188,10 @@
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.profile .profile-actions button.icon:not(:last-child) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 520px) {
|
||||
.profile .banner {
|
||||
width: 100%;
|
||||
@ -194,5 +199,17 @@
|
||||
height: 300px;
|
||||
margin-bottom: -100px;
|
||||
}
|
||||
.profile .profile-actions button.icon:not(:last-child) {
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.profile .npub {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.qr-modal .modal-body {
|
||||
width: unset;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { useSelector } from "react-redux";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
import Link from "Icons/Link";
|
||||
import Qr from "Icons/Qr";
|
||||
import Zap from "Icons/Zap";
|
||||
import Envelope from "Icons/Envelope";
|
||||
import { useUserProfile } from "Feed/ProfileFeed";
|
||||
@ -22,9 +23,12 @@ import FollowersList from "Element/FollowersList";
|
||||
import BlockList from "Element/BlockList";
|
||||
import MutedList from "Element/MutedList";
|
||||
import FollowsList from "Element/FollowsList";
|
||||
import IconButton from "Element/IconButton";
|
||||
import { RootState } from "State/Store";
|
||||
import { HexKey } from "Nostr";
|
||||
import FollowsYou from "Element/FollowsYou"
|
||||
import QrCode from "Element/QrCode";
|
||||
import Modal from "Element/Modal";
|
||||
|
||||
enum ProfileTab {
|
||||
Notes = "Notes",
|
||||
@ -46,8 +50,9 @@ export default function ProfilePage() {
|
||||
const isMe = loginPubKey === id;
|
||||
const [showLnQr, setShowLnQr] = useState<boolean>(false);
|
||||
const [tab, setTab] = useState(ProfileTab.Notes);
|
||||
const [showProfileQr, setShowProfileQr] = useState<boolean>(false);
|
||||
const aboutText = user?.about || ''
|
||||
const about = Text({ content: user?.about || '', tags: [], users: new Map() })
|
||||
const about = Text({ content: aboutText, tags: [], users: new Map() })
|
||||
const lnurl = extractLnAddress(user?.lud16 || user?.lud06 || "");
|
||||
|
||||
useEffect(() => {
|
||||
@ -132,41 +137,49 @@ export default function ProfilePage() {
|
||||
)
|
||||
}
|
||||
|
||||
function renderIcons() {
|
||||
return (
|
||||
<div className="icon-actions">
|
||||
<IconButton onClick={() => setShowProfileQr(true)}>
|
||||
<Qr width={14} height={16} />
|
||||
</IconButton>
|
||||
{showProfileQr && (
|
||||
<Modal className="qr-modal" onClose={() => setShowProfileQr(false)}>
|
||||
<QrCode data={`nostr:${hexToBech32("npub", id)}`} link={undefined} className="m10"/>
|
||||
</Modal>
|
||||
)}
|
||||
{isMe ? (
|
||||
<>
|
||||
<LogoutButton />
|
||||
<button type="button" onClick={() => navigate("/settings")}>
|
||||
Settings
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<IconButton onClick={() => setShowLnQr(true)}>
|
||||
<Zap width={14} height={16} />
|
||||
</IconButton>
|
||||
{!loggedOut && (
|
||||
<>
|
||||
<IconButton onClick={() => navigate(`/messages/${hexToBech32("npub", id)}`)}>
|
||||
<Envelope width={16} height={13} />
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function userDetails() {
|
||||
return (
|
||||
<div className="details-wrapper">
|
||||
{username()}
|
||||
<div className="profile-actions">
|
||||
{isMe ? (
|
||||
<>
|
||||
<LogoutButton />
|
||||
<button type="button" onClick={() => navigate("/settings")}>
|
||||
Settings
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
className="icon"
|
||||
type="button"
|
||||
onClick={() => setShowLnQr(true)}
|
||||
>
|
||||
<Zap width={14} height={16} />
|
||||
</button>
|
||||
{!loggedOut && (
|
||||
<>
|
||||
<button
|
||||
className="icon"
|
||||
type="button"
|
||||
onClick={() => navigate(`/messages/${hexToBech32("npub", id)}`)}
|
||||
>
|
||||
<Envelope width={16} height={13} />
|
||||
</button>
|
||||
<FollowButton pubkey={id} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{renderIcons()}
|
||||
{!isMe && <FollowButton pubkey={id} />}
|
||||
</div>
|
||||
{bio()}
|
||||
</div>
|
||||
|
@ -171,11 +171,17 @@ button.icon {
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--font-color);
|
||||
min-height: 28px;
|
||||
}
|
||||
|
||||
button.icon .icon-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
button.icon:hover {
|
||||
color: white;
|
||||
background: var(--highlight);
|
||||
color: var(--highlight);
|
||||
}
|
||||
|
||||
.btn {
|
||||
@ -420,11 +426,7 @@ body.scroll-lock {
|
||||
}
|
||||
|
||||
.tabs>div {
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tabs>div:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user