Feature: Update Profile Info Card (#93)

* feat: add Lightning Address copy functionality to ProfileInfoCard

* feat: add website link functionality to ProfileInfoCard

---------

Co-authored-by: highperfocused <highperfocused@pm.me>
This commit is contained in:
mroxso
2025-04-21 18:08:45 +02:00
committed by GitHub
parent 986e151948
commit e3ba9f1cc6
2 changed files with 54 additions and 2 deletions

View File

@@ -20,8 +20,9 @@ import {
DrawerTrigger,
} from "@/components/ui/drawer"
import { Input } from './ui/input';
import { Share1Icon } from '@radix-ui/react-icons';
import { Share1Icon, LightningBoltIcon, GlobeIcon } from '@radix-ui/react-icons';
import { toast } from './ui/use-toast';
import { Globe } from 'lucide-react';
interface ProfileInfoCardProps {
pubkey: string;
@@ -47,6 +48,8 @@ const ProfileInfoCard: React.FC<ProfileInfoCardProps> = React.memo(({ pubkey })
const title = userData?.username || userData?.display_name || userData?.name || userData?.npub || npubShortened;
const description = userData?.about?.replace(/(?:\r\n|\r|\n)/g, '<br>');
const nip05 = userData?.nip05;
const lightningAddress = userData?.lud16;
const website = userData?.website;
const handleCopyLink = async () => {
try {
@@ -80,6 +83,36 @@ const ProfileInfoCard: React.FC<ProfileInfoCardProps> = React.memo(({ pubkey })
}
};
const handleCopyLightningAddress = async () => {
if (!lightningAddress) return;
try {
await navigator.clipboard.writeText(lightningAddress);
toast({
description: 'Lightning Address copied to clipboard',
title: 'Copied'
});
} catch (err) {
toast({
description: 'Error copying Lightning Address to clipboard',
title: 'Error',
variant: 'destructive'
});
}
};
const handleOpenWebsite = () => {
if (!website) return;
// Add https:// prefix if not present
let url = website;
if (!/^https?:\/\//i.test(url)) {
url = 'https://' + url;
}
window.open(url, '_blank');
};
return (
<div className='py-6'>
<Card>
@@ -95,6 +128,18 @@ const ProfileInfoCard: React.FC<ProfileInfoCardProps> = React.memo(({ pubkey })
<div className="text-sm text-muted-foreground">
<NIP05 nip05={nip05?.toString() ?? ''} pubkey={pubkey} />
</div>
{lightningAddress && (
<div className="text-sm text-muted-foreground flex items-center gap-1 cursor-pointer hover:text-purple-400 transition-colors" onClick={handleCopyLightningAddress}>
<LightningBoltIcon className="h-4 w-4 text-yellow-500" />
<span>{lightningAddress}</span>
</div>
)}
{website && (
<div className="text-sm text-muted-foreground flex items-center gap-1 cursor-pointer hover:text-purple-400 transition-colors" onClick={handleOpenWebsite}>
<Globe className="h-4 w-4 text-purple-500" />
<span>{website}</span>
</div>
)}
</div>
</div>
<div>

View File

@@ -1,4 +1,5 @@
import { CheckIcon, ReloadIcon } from "@radix-ui/react-icons";
import { BadgeCheck, Check } from "lucide-react";
import React, { useState, useEffect } from 'react';
interface NIP05Props {
@@ -33,8 +34,14 @@ const NIP05: React.FC<NIP05Props> = ({ nip05, pubkey }) => {
<div style={{ display: 'flex', alignItems: 'center' }}>
{nip05.length > 0 &&
<>
{isLoading ? (
<ReloadIcon className="mr-1 h-4 w-4 animate-spin" />
) : isValid ? (
<BadgeCheck className="mr-1 h-4 w-4 text-blue-500" />
) : (
<span className="mr-1 text-red-500"></span>
)}
{ name === "_" ? domain : nip05 }
{isLoading ? <ReloadIcon className="mx-2 h-4 w-4 animate-spin" /> : isValid ? <CheckIcon className="mx-2 h-4 w-4" /> : <span className="mx-2 text-red-500"></span>}
</>
}
</div>