mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-18 11:13:30 +00:00
fully support nip05
This commit is contained in:
parent
0d207d471c
commit
cc315a190a
@ -36,7 +36,6 @@
|
|||||||
"@tauri-apps/plugin-clipboard-manager": "github:tauri-apps/tauri-plugin-clipboard-manager#v2",
|
"@tauri-apps/plugin-clipboard-manager": "github:tauri-apps/tauri-plugin-clipboard-manager#v2",
|
||||||
"@tauri-apps/plugin-dialog": "github:tauri-apps/tauri-plugin-dialog#v2",
|
"@tauri-apps/plugin-dialog": "github:tauri-apps/tauri-plugin-dialog#v2",
|
||||||
"@tauri-apps/plugin-fs": "github:tauri-apps/tauri-plugin-fs#v2",
|
"@tauri-apps/plugin-fs": "github:tauri-apps/tauri-plugin-fs#v2",
|
||||||
"@tauri-apps/plugin-http": "github:tauri-apps/tauri-plugin-http#v2",
|
|
||||||
"@tauri-apps/plugin-notification": "github:tauri-apps/tauri-plugin-notification#v2",
|
"@tauri-apps/plugin-notification": "github:tauri-apps/tauri-plugin-notification#v2",
|
||||||
"@tauri-apps/plugin-os": "github:tauri-apps/tauri-plugin-os#v2",
|
"@tauri-apps/plugin-os": "github:tauri-apps/tauri-plugin-os#v2",
|
||||||
"@tauri-apps/plugin-process": "github:tauri-apps/tauri-plugin-process#v2",
|
"@tauri-apps/plugin-process": "github:tauri-apps/tauri-plugin-process#v2",
|
||||||
|
@ -55,9 +55,6 @@ dependencies:
|
|||||||
'@tauri-apps/plugin-fs':
|
'@tauri-apps/plugin-fs':
|
||||||
specifier: github:tauri-apps/tauri-plugin-fs#v2
|
specifier: github:tauri-apps/tauri-plugin-fs#v2
|
||||||
version: github.com/tauri-apps/tauri-plugin-fs/c90fd8bcad3be92f34a0642d67ab1a6ad9f73dee
|
version: github.com/tauri-apps/tauri-plugin-fs/c90fd8bcad3be92f34a0642d67ab1a6ad9f73dee
|
||||||
'@tauri-apps/plugin-http':
|
|
||||||
specifier: github:tauri-apps/tauri-plugin-http#v2
|
|
||||||
version: github.com/tauri-apps/tauri-plugin-http/50bc7956907eef54a20255b62ea57ff4c2e8585a
|
|
||||||
'@tauri-apps/plugin-notification':
|
'@tauri-apps/plugin-notification':
|
||||||
specifier: github:tauri-apps/tauri-plugin-notification#v2
|
specifier: github:tauri-apps/tauri-plugin-notification#v2
|
||||||
version: github.com/tauri-apps/tauri-plugin-notification/66c0779854575ec7860eadcd98673c39627e81a6
|
version: github.com/tauri-apps/tauri-plugin-notification/66c0779854575ec7860eadcd98673c39627e81a6
|
||||||
@ -7159,14 +7156,6 @@ packages:
|
|||||||
'@tauri-apps/api': 2.0.0-alpha.6
|
'@tauri-apps/api': 2.0.0-alpha.6
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
github.com/tauri-apps/tauri-plugin-http/50bc7956907eef54a20255b62ea57ff4c2e8585a:
|
|
||||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-http/tar.gz/50bc7956907eef54a20255b62ea57ff4c2e8585a}
|
|
||||||
name: '@tauri-apps/plugin-http'
|
|
||||||
version: 2.0.0-alpha.1
|
|
||||||
dependencies:
|
|
||||||
'@tauri-apps/api': 2.0.0-alpha.6
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
github.com/tauri-apps/tauri-plugin-notification/66c0779854575ec7860eadcd98673c39627e81a6:
|
github.com/tauri-apps/tauri-plugin-notification/66c0779854575ec7860eadcd98673c39627e81a6:
|
||||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-notification/tar.gz/66c0779854575ec7860eadcd98673c39627e81a6}
|
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-notification/tar.gz/66c0779854575ec7860eadcd98673c39627e81a6}
|
||||||
name: '@tauri-apps/plugin-notification'
|
name: '@tauri-apps/plugin-notification'
|
||||||
|
@ -27,7 +27,7 @@ export function User({ pubkey, fallback }: { pubkey: string; fallback?: string }
|
|||||||
/>
|
/>
|
||||||
<div className="flex w-full flex-1 flex-col items-start text-start">
|
<div className="flex w-full flex-1 flex-col items-start text-start">
|
||||||
<p className="max-w-[15rem] truncate font-medium leading-tight text-white">
|
<p className="max-w-[15rem] truncate font-medium leading-tight text-white">
|
||||||
{user?.name || user?.display_name || user?.nip05}
|
{user?.name || user?.display_name}
|
||||||
</p>
|
</p>
|
||||||
<span className="max-w-[15rem] truncate leading-tight text-white/50">
|
<span className="max-w-[15rem] truncate leading-tight text-white/50">
|
||||||
{displayNpub(pubkey, 16)}
|
{displayNpub(pubkey, 16)}
|
||||||
|
@ -28,7 +28,7 @@ export function UserRelay({ pubkey }: { pubkey: string }) {
|
|||||||
className="h-5 w-5 shrink-0 rounded object-cover"
|
className="h-5 w-5 shrink-0 rounded object-cover"
|
||||||
/>
|
/>
|
||||||
<span className="truncate text-sm font-medium leading-none text-white">
|
<span className="truncate text-sm font-medium leading-none text-white">
|
||||||
{user?.name || user?.display_name || user?.nip05 || displayNpub(pubkey, 16)}
|
{user?.name || user?.display_name || displayNpub(pubkey, 16)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,7 +38,7 @@ export function ChatsListItem({ pubkey }: { pubkey: string }) {
|
|||||||
/>
|
/>
|
||||||
<div className="inline-flex w-full flex-1 items-center justify-between">
|
<div className="inline-flex w-full flex-1 items-center justify-between">
|
||||||
<h5 className="max-w-[10rem] truncate">
|
<h5 className="max-w-[10rem] truncate">
|
||||||
{user?.nip05 || user?.name || user?.display_name || displayNpub(pubkey, 16)}
|
{user?.name || user?.display_name || displayNpub(pubkey, 16)}
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { Image } from '@shared/image';
|
import { Image } from '@shared/image';
|
||||||
|
import { NIP05 } from '@shared/nip05';
|
||||||
|
|
||||||
import { useProfile } from '@utils/hooks/useProfile';
|
import { useProfile } from '@utils/hooks/useProfile';
|
||||||
import { displayNpub } from '@utils/shortenKey';
|
import { displayNpub } from '@utils/shortenKey';
|
||||||
@ -23,9 +24,17 @@ export function ChatSidebar({ pubkey }: { pubkey: string }) {
|
|||||||
<h3 className="text-lg font-semibold leading-none">
|
<h3 className="text-lg font-semibold leading-none">
|
||||||
{user?.display_name || user?.name}
|
{user?.display_name || user?.name}
|
||||||
</h3>
|
</h3>
|
||||||
<h5 className="leading-none text-white/50">
|
{user?.nip05 ? (
|
||||||
{user?.nip05 || displayNpub(pubkey, 16)}
|
<NIP05
|
||||||
</h5>
|
pubkey={pubkey}
|
||||||
|
nip05={user?.nip05}
|
||||||
|
className="leading-none text-white/50"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span className="leading-none text-white/50">
|
||||||
|
{displayNpub(pubkey, 16)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="leading-tight">{user?.bio || user?.about}</p>
|
<p className="leading-tight">{user?.bio || user?.about}</p>
|
||||||
|
@ -25,7 +25,7 @@ export function NotiUser({ pubkey }: { pubkey: string }) {
|
|||||||
className="h-11 w-11 shrink-0 rounded-lg object-cover"
|
className="h-11 w-11 shrink-0 rounded-lg object-cover"
|
||||||
/>
|
/>
|
||||||
<span className="max-w-[10rem] flex-1 truncate font-medium leading-none text-white">
|
<span className="max-w-[10rem] flex-1 truncate font-medium leading-none text-white">
|
||||||
{user?.nip05 || user?.name || user?.display_name || displayNpub(pubkey, 16)}
|
{user?.name || user?.display_name || displayNpub(pubkey, 16)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -7,10 +7,11 @@ import { UserStats } from '@app/users/components/stats';
|
|||||||
import { useStorage } from '@libs/storage/provider';
|
import { useStorage } from '@libs/storage/provider';
|
||||||
|
|
||||||
import { Image } from '@shared/image';
|
import { Image } from '@shared/image';
|
||||||
|
import { NIP05 } from '@shared/nip05';
|
||||||
|
|
||||||
import { useNostr } from '@utils/hooks/useNostr';
|
import { useNostr } from '@utils/hooks/useNostr';
|
||||||
import { useProfile } from '@utils/hooks/useProfile';
|
import { useProfile } from '@utils/hooks/useProfile';
|
||||||
import { shortenKey } from '@utils/shortenKey';
|
import { displayNpub } from '@utils/shortenKey';
|
||||||
|
|
||||||
export function UserProfile({ pubkey }: { pubkey: string }) {
|
export function UserProfile({ pubkey }: { pubkey: string }) {
|
||||||
const { db } = useStorage();
|
const { db } = useStorage();
|
||||||
@ -68,13 +69,21 @@ export function UserProfile({ pubkey }: { pubkey: string }) {
|
|||||||
/>
|
/>
|
||||||
<div className="mt-2 flex flex-1 flex-col gap-6">
|
<div className="mt-2 flex flex-1 flex-col gap-6">
|
||||||
<div className="flex flex-col items-center gap-1">
|
<div className="flex flex-col items-center gap-1">
|
||||||
<div className="inline-flex flex-col gap-1.5">
|
<div className="inline-flex flex-col items-center gap-1.5">
|
||||||
<h5 className="text-center text-xl font-semibold leading-none">
|
<h5 className="text-center text-xl font-semibold leading-none">
|
||||||
{user.display_name || user.displayName || user.name || 'No name'}
|
{user.display_name || user.displayName || user.name || 'No name'}
|
||||||
</h5>
|
</h5>
|
||||||
<span className="max-w-[15rem] truncate text-center leading-none text-white/50">
|
{user.nip05 ? (
|
||||||
{user.nip05 || user.username || shortenKey(pubkey)}
|
<NIP05
|
||||||
</span>
|
pubkey={pubkey}
|
||||||
|
nip05={user?.nip05}
|
||||||
|
className="max-w-[15rem] truncate text-sm leading-none text-white/50"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span className="max-w-[15rem] truncate text-sm leading-none text-white/50">
|
||||||
|
{displayNpub(pubkey, 16)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
{user.about || user.bio ? (
|
{user.about || user.bio ? (
|
||||||
|
@ -67,7 +67,7 @@ export function ActiveAccount() {
|
|||||||
/>
|
/>
|
||||||
<div className="flex w-full flex-1 flex-col items-start gap-1.5">
|
<div className="flex w-full flex-1 flex-col items-start gap-1.5">
|
||||||
<p className="max-w-[10rem] truncate font-bold leading-none text-white">
|
<p className="max-w-[10rem] truncate font-bold leading-none text-white">
|
||||||
{user?.name || user?.display_name || user?.nip05}
|
{user?.name || user?.display_name}
|
||||||
</p>
|
</p>
|
||||||
<span className="max-w-[8rem] truncate text-sm leading-none text-white/50">
|
<span className="max-w-[8rem] truncate text-sm leading-none text-white/50">
|
||||||
{displayNpub(db.account.pubkey, 16)}
|
{displayNpub(db.account.pubkey, 16)}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Image } from '@shared/image';
|
import { Image } from '@shared/image';
|
||||||
|
|
||||||
import { useProfile } from '@utils/hooks/useProfile';
|
import { useProfile } from '@utils/hooks/useProfile';
|
||||||
|
import { displayNpub } from '@utils/shortenKey';
|
||||||
|
|
||||||
export function ComposerUser({ pubkey }: { pubkey: string }) {
|
export function ComposerUser({ pubkey }: { pubkey: string }) {
|
||||||
const { user } = useProfile(pubkey);
|
const { user } = useProfile(pubkey);
|
||||||
@ -13,9 +14,7 @@ export function ComposerUser({ pubkey }: { pubkey: string }) {
|
|||||||
className="h-10 w-10 shrink-0 rounded-lg"
|
className="h-10 w-10 shrink-0 rounded-lg"
|
||||||
/>
|
/>
|
||||||
<h5 className="text-base font-semibold leading-none text-white">
|
<h5 className="text-base font-semibold leading-none text-white">
|
||||||
{user?.nip05 || user?.name || (
|
{user?.name || user?.display_name || displayNpub(pubkey, 16)}
|
||||||
<div className="h-3 w-20 animate-pulse rounded-sm bg-zinc-700" />
|
|
||||||
)}
|
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -56,3 +56,4 @@ export * from './expand';
|
|||||||
export * from './focus';
|
export * from './focus';
|
||||||
export * from './chevronUp';
|
export * from './chevronUp';
|
||||||
export * from './secure';
|
export * from './secure';
|
||||||
|
export * from './verified';
|
||||||
|
21
src/shared/icons/verified.tsx
Normal file
21
src/shared/icons/verified.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { SVGProps } from 'react';
|
||||||
|
|
||||||
|
export function VerifiedIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm3.58 7.975a.75.75 0 00-1.16-.95l-3.976 4.859L9.03 12.47a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.11-.055l4.5-5.5z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
73
src/shared/nip05.tsx
Normal file
73
src/shared/nip05.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
import { UnverifiedIcon, VerifiedIcon } from '@shared/icons';
|
||||||
|
|
||||||
|
interface NIP05 {
|
||||||
|
names: {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NIP05({
|
||||||
|
pubkey,
|
||||||
|
nip05,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
pubkey: string;
|
||||||
|
nip05: string;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
const { status, data } = useQuery(
|
||||||
|
[nip05],
|
||||||
|
async () => {
|
||||||
|
try {
|
||||||
|
const username = nip05.split('@')[0];
|
||||||
|
const service = nip05.split('@')[1];
|
||||||
|
// #TODO: use tauri native fetch to avoid CORS
|
||||||
|
const verifyURL = `https://${service}/.well-known/nostr.json?name=${username}`;
|
||||||
|
|
||||||
|
const res = await fetch(verifyURL, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) throw new Error(`Failed to fetch NIP-05 service: ${nip05}`);
|
||||||
|
|
||||||
|
const data: NIP05 = await res.json();
|
||||||
|
|
||||||
|
if (data.names) {
|
||||||
|
if (data.names.username !== pubkey) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Failed to verify NIP-05, error: ${e}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refetchOnMount: false,
|
||||||
|
refetchOnReconnect: false,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
staleTime: Infinity,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (status === 'loading') {
|
||||||
|
<div className="h-3 w-20 animate-pulse rounded bg-white/10" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={twMerge('leadning-none inline-flex items-center gap-1', className)}>
|
||||||
|
<p>{nip05}</p>
|
||||||
|
<div className="shrink-0">
|
||||||
|
{data === true ? (
|
||||||
|
<VerifiedIcon className="h-3 w-3 text-green-500" />
|
||||||
|
) : (
|
||||||
|
<UnverifiedIcon className="h-3 w-3 text-red-500" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -17,17 +17,13 @@ export function MentionUser({ pubkey }: { pubkey: string }) {
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
setWidget(db, {
|
setWidget(db, {
|
||||||
kind: WidgetKinds.local.user,
|
kind: WidgetKinds.local.user,
|
||||||
title: user?.nip05 || user?.name || user?.display_name,
|
title: user?.name || user?.display_name,
|
||||||
content: pubkey,
|
content: pubkey,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="break-words text-fuchsia-400 hover:text-fuchsia-500"
|
className="break-words text-fuchsia-400 hover:text-fuchsia-500"
|
||||||
>
|
>
|
||||||
{user?.nip05 ||
|
{user?.name || user?.display_name || user?.username || displayNpub(pubkey, 16)}
|
||||||
user?.name ||
|
|
||||||
user?.display_name ||
|
|
||||||
user?.username ||
|
|
||||||
displayNpub(pubkey, 16)}
|
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ export function NoteReplyForm({ id, pubkey }: { id: string; pubkey: string }) {
|
|||||||
<div>
|
<div>
|
||||||
<p className="mb-1 text-sm leading-none text-white/50">Reply as</p>
|
<p className="mb-1 text-sm leading-none text-white/50">Reply as</p>
|
||||||
<p className="text-sm font-medium leading-none text-white">
|
<p className="text-sm font-medium leading-none text-white">
|
||||||
{user?.nip05 || user?.name || displayNpub(pubkey, 16)}
|
{user?.name || displayNpub(pubkey, 16)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,7 +19,7 @@ export function RepostUser({ pubkey }: { pubkey: string }) {
|
|||||||
/>
|
/>
|
||||||
<div className="inline-flex items-baseline gap-1">
|
<div className="inline-flex items-baseline gap-1">
|
||||||
<h5 className="max-w-[18rem] truncate text-white/50">
|
<h5 className="max-w-[18rem] truncate text-white/50">
|
||||||
{user?.nip05 || user?.name || user?.display_name || shortenKey(pubkey)}
|
{user?.name || user?.display_name || shortenKey(pubkey)}
|
||||||
</h5>
|
</h5>
|
||||||
<span className="text-white/50">reposted</span>
|
<span className="text-white/50">reposted</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,6 +3,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
import { Image } from '@shared/image';
|
import { Image } from '@shared/image';
|
||||||
|
import { NIP05 } from '@shared/nip05';
|
||||||
|
|
||||||
import { formatCreatedAt } from '@utils/createdAt';
|
import { formatCreatedAt } from '@utils/createdAt';
|
||||||
import { useProfile } from '@utils/hooks/useProfile';
|
import { useProfile } from '@utils/hooks/useProfile';
|
||||||
@ -79,7 +80,7 @@ export function User({
|
|||||||
size === 'small' ? 'max-w-[10rem]' : 'max-w-[15rem]'
|
size === 'small' ? 'max-w-[10rem]' : 'max-w-[15rem]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{user?.nip05 || user?.name || user?.display_name || displayNpub(pubkey, 16)}
|
{user?.display_name || user?.name || displayNpub(pubkey, 16)}
|
||||||
</h5>
|
</h5>
|
||||||
<span className="leading-none text-white/50">·</span>
|
<span className="leading-none text-white/50">·</span>
|
||||||
<span className="leading-none text-white/50">{createdAt}</span>
|
<span className="leading-none text-white/50">{createdAt}</span>
|
||||||
@ -87,7 +88,7 @@ export function User({
|
|||||||
</div>
|
</div>
|
||||||
<Popover.Portal>
|
<Popover.Portal>
|
||||||
<Popover.Content
|
<Popover.Content
|
||||||
className="w-[300px] overflow-hidden rounded-md bg-white/10 backdrop-blur-3xl backdrop-blur-xl focus:outline-none"
|
className="w-[300px] overflow-hidden rounded-md bg-white/10 backdrop-blur-3xl focus:outline-none"
|
||||||
sideOffset={5}
|
sideOffset={5}
|
||||||
>
|
>
|
||||||
<div className="flex gap-2.5 border-b border-white/5 px-3 py-3">
|
<div className="flex gap-2.5 border-b border-white/5 px-3 py-3">
|
||||||
@ -101,9 +102,17 @@ export function User({
|
|||||||
<h5 className="text-sm font-semibold leading-none">
|
<h5 className="text-sm font-semibold leading-none">
|
||||||
{user?.display_name || user?.name || user?.username}
|
{user?.display_name || user?.name || user?.username}
|
||||||
</h5>
|
</h5>
|
||||||
<span className="max-w-[10rem] truncate text-sm leading-none text-white/50">
|
{user?.nip05 ? (
|
||||||
{user?.nip05 || displayNpub(pubkey, 16)}
|
<NIP05
|
||||||
</span>
|
pubkey={pubkey}
|
||||||
|
nip05={user?.nip05}
|
||||||
|
className="max-w-[15rem] truncate text-sm leading-none text-white/50"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span className="max-w-[15rem] truncate text-sm leading-none text-white/50">
|
||||||
|
{displayNpub(pubkey, 16)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="line-clamp-3 break-all leading-tight text-white">
|
<p className="line-clamp-3 break-all leading-tight text-white">
|
||||||
|
@ -6,6 +6,7 @@ import { UserStats } from '@app/users/components/stats';
|
|||||||
import { useStorage } from '@libs/storage/provider';
|
import { useStorage } from '@libs/storage/provider';
|
||||||
|
|
||||||
import { Image } from '@shared/image';
|
import { Image } from '@shared/image';
|
||||||
|
import { NIP05 } from '@shared/nip05';
|
||||||
|
|
||||||
import { useNostr } from '@utils/hooks/useNostr';
|
import { useNostr } from '@utils/hooks/useNostr';
|
||||||
import { useProfile } from '@utils/hooks/useProfile';
|
import { useProfile } from '@utils/hooks/useProfile';
|
||||||
@ -58,9 +59,17 @@ export function UserProfile({ pubkey }: { pubkey: string }) {
|
|||||||
<h5 className="text-lg font-semibold leading-none">
|
<h5 className="text-lg font-semibold leading-none">
|
||||||
{user?.displayName || user?.name || 'No name'}
|
{user?.displayName || user?.name || 'No name'}
|
||||||
</h5>
|
</h5>
|
||||||
<span className="max-w-[15rem] truncate text-sm leading-none text-white/50">
|
{user?.nip05 ? (
|
||||||
{user?.nip05 || displayNpub(pubkey, 16)}
|
<NIP05
|
||||||
</span>
|
pubkey={pubkey}
|
||||||
|
nip05={user?.nip05}
|
||||||
|
className="max-w-[15rem] truncate text-sm leading-none text-white/50"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span className="max-w-[15rem] truncate text-sm leading-none text-white/50">
|
||||||
|
{displayNpub(pubkey, 16)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<p className="mt-2 max-w-[500px] select-text break-words text-white">
|
<p className="mt-2 max-w-[500px] select-text break-words text-white">
|
||||||
|
Loading…
Reference in New Issue
Block a user