feat: qrcode

This commit is contained in:
codytseng
2024-11-12 09:51:18 +08:00
parent 3f9042b3be
commit 10bfeb23ad
7 changed files with 72 additions and 31 deletions

View File

@@ -30,7 +30,7 @@ export default function ShortTextNoteCard({
}}
>
<Card
className={`hover:bg-muted/50 text-left cursor-pointer ${size === 'normal' ? 'p-4' : 'p-2'}`}
className={`hover:bg-muted/50 text-left cursor-pointer ${size === 'normal' ? 'p-4' : 'p-3'}`}
>
<Note
size={size}

View File

@@ -7,7 +7,7 @@ import {
import { embeddedNpubRenderer } from '@renderer/embedded/EmbeddedNpub'
import { useMemo } from 'react'
export default function ProfileAbout({ about }: { about?: string }) {
export default function ProfileAbout({ about, className }: { about?: string; className?: string }) {
const nodes = useMemo(() => {
return about
? embedded(about, [
@@ -19,5 +19,5 @@ export default function ProfileAbout({ about }: { about?: string }) {
: null
}, [about])
return <>{nodes}</>
return <div className={className}>{nodes}</div>
}

View File

@@ -0,0 +1,27 @@
import { formatNpub } from '@renderer/lib/pubkey'
import { Check, Copy } from 'lucide-react'
import { nip19 } from 'nostr-tools'
import { useMemo, useState } from 'react'
export default function PubkeyCopy({ pubkey }: { pubkey: string }) {
const npub = useMemo(() => (pubkey ? nip19.npubEncode(pubkey) : ''), [pubkey])
const [copied, setCopied] = useState(false)
const copyNpub = () => {
if (!npub) return
navigator.clipboard.writeText(npub)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
return (
<div
className="flex gap-2 text-sm text-muted-foreground items-center bg-muted w-fit px-2 rounded-full hover:text-foreground cursor-pointer"
onClick={() => copyNpub()}
>
<div>{formatNpub(npub, 24)}</div>
{copied ? <Check size={14} /> : <Copy size={14} />}
</div>
)
}

View File

@@ -0,0 +1,23 @@
import { Popover, PopoverContent, PopoverTrigger } from '@renderer/components/ui/popover'
import { QrCode } from 'lucide-react'
import { nip19 } from 'nostr-tools'
import { useMemo } from 'react'
import { QRCodeSVG } from 'qrcode.react'
export default function QrCodePopover({ pubkey }: { pubkey: string }) {
const npub = useMemo(() => (pubkey ? nip19.npubEncode(pubkey) : ''), [pubkey])
if (!npub) return null
return (
<Popover>
<PopoverTrigger>
<div className="bg-muted rounded-full h-5 w-5 flex flex-col items-center justify-center text-muted-foreground hover:text-foreground">
<QrCode size={14} />
</div>
</PopoverTrigger>
<PopoverContent className="w-fit h-fit">
<QRCodeSVG value={`nostr:${npub}`} />
</PopoverContent>
</Popover>
)
}

View File

@@ -9,33 +9,25 @@ import { useFetchFollowings, useFetchProfile } from '@renderer/hooks'
import { useFetchRelayList } from '@renderer/hooks/useFetchRelayList'
import SecondaryPageLayout from '@renderer/layouts/SecondaryPageLayout'
import { toFollowingList } from '@renderer/lib/link'
import { formatNpub, generateImageByPubkey } from '@renderer/lib/pubkey'
import { generateImageByPubkey } from '@renderer/lib/pubkey'
import { SecondaryPageLink } from '@renderer/PageManager'
import { useNostr } from '@renderer/providers/NostrProvider'
import { Copy } from 'lucide-react'
import { nip19 } from 'nostr-tools'
import { useMemo, useState } from 'react'
import { useMemo } from 'react'
import PubkeyCopy from './PubkeyCopy'
import QrCodePopover from './QrCodePopover'
export default function ProfilePage({ pubkey }: { pubkey?: string }) {
const { banner, username, nip05, about, avatar } = useFetchProfile(pubkey)
const relayList = useFetchRelayList(pubkey)
const [copied, setCopied] = useState(false)
const { pubkey: accountPubkey } = useNostr()
const { followings } = useFetchFollowings(pubkey)
const isFollowingYou = useMemo(
() => !!accountPubkey && accountPubkey !== pubkey && followings.includes(accountPubkey),
[followings, pubkey]
)
const npub = useMemo(() => (pubkey ? nip19.npubEncode(pubkey) : undefined), [pubkey])
const defaultImage = useMemo(() => (pubkey ? generateImageByPubkey(pubkey) : ''), [pubkey])
if (!pubkey || !npub) return null
const copyNpub = () => {
navigator.clipboard.writeText(npub)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
if (!pubkey) return null
return (
<SecondaryPageLayout titlebarContent={username}>
@@ -63,22 +55,11 @@ export default function ProfilePage({ pubkey }: { pubkey?: string }) {
<div className="pt-2">
<div className="text-xl font-semibold">{username}</div>
{nip05 && <Nip05 nip05={nip05} pubkey={pubkey} />}
<div
className="mt-1 flex gap-2 text-sm text-muted-foreground items-center bg-muted w-fit px-2 rounded-full hover:text-foreground cursor-pointer"
onClick={() => copyNpub()}
>
{copied ? (
<div>copied!</div>
) : (
<>
<div>{formatNpub(npub, 24)}</div>
<Copy size={14} />
</>
)}
</div>
<div className="text-wrap break-words whitespace-pre-wrap mt-2">
<ProfileAbout about={about} />
<div className="flex gap-1 mt-1">
<PubkeyCopy pubkey={pubkey} />
<QrCodePopover pubkey={pubkey} />
</div>
<ProfileAbout about={about} className="text-wrap break-words whitespace-pre-wrap mt-2" />
<SecondaryPageLink
to={toFollowingList(pubkey)}
className="mt-2 flex gap-1 hover:underline text-sm"