mirror of
https://gitlab.com/soapbox-pub/mkstack.git
synced 2025-08-27 13:09:22 +00:00
Generate a deterministic name from pubkey if no display name is set
This commit is contained in:
parent
865ca7039f
commit
7c5fe75572
@ -101,4 +101,36 @@ describe('NoteContent', () => {
|
|||||||
expect(nostrHashtag).toHaveAttribute('href', '/t/nostr');
|
expect(nostrHashtag).toHaveAttribute('href', '/t/nostr');
|
||||||
expect(bitcoinHashtag).toHaveAttribute('href', '/t/bitcoin');
|
expect(bitcoinHashtag).toHaveAttribute('href', '/t/bitcoin');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('generates deterministic names for users without metadata and styles them differently', () => {
|
||||||
|
// Use a valid npub for testing
|
||||||
|
const event: NostrEvent = {
|
||||||
|
id: 'test-id',
|
||||||
|
pubkey: 'test-pubkey',
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: 1,
|
||||||
|
tags: [],
|
||||||
|
content: `Mentioning nostr:npub1zg69v7ys40x77y352eufp27daufrg4ncjz4ummcjx3t83y9tehhsqepuh0`,
|
||||||
|
sig: 'test-sig',
|
||||||
|
};
|
||||||
|
|
||||||
|
render(
|
||||||
|
<TestApp>
|
||||||
|
<NoteContent event={event} />
|
||||||
|
</TestApp>
|
||||||
|
);
|
||||||
|
|
||||||
|
// The mention should be rendered with a deterministic name
|
||||||
|
const mention = screen.getByRole('link');
|
||||||
|
expect(mention).toBeInTheDocument();
|
||||||
|
|
||||||
|
// Should have muted styling for generated names (gray instead of blue)
|
||||||
|
expect(mention).toHaveClass('text-gray-500');
|
||||||
|
expect(mention).not.toHaveClass('text-blue-500');
|
||||||
|
|
||||||
|
// The text should start with @ and contain a generated name (not a truncated npub)
|
||||||
|
const linkText = mention.textContent;
|
||||||
|
expect(linkText).not.toMatch(/^@npub1/); // Should not be a truncated npub
|
||||||
|
expect(linkText).toEqual("@SwiftFalcon");
|
||||||
|
});
|
||||||
});
|
});
|
@ -20,7 +20,7 @@ export function NoteContent({
|
|||||||
const text = event.content;
|
const text = event.content;
|
||||||
|
|
||||||
// Regex to find URLs, Nostr references, and hashtags
|
// Regex to find URLs, Nostr references, and hashtags
|
||||||
const regex = /(https?:\/\/[^\s]+)|nostr:(npub1|note1|nprofile1|nevent1)([a-z0-9]+)|(#\w+)/g;
|
const regex = /(https?:\/\/[^\s]+)|nostr:(npub1|note1|nprofile1|nevent1)([023456789acdefghjklmnpqrstuvwxyz]+)|(#\w+)/g;
|
||||||
|
|
||||||
const parts: React.ReactNode[] = [];
|
const parts: React.ReactNode[] = [];
|
||||||
let lastIndex = 0;
|
let lastIndex = 0;
|
||||||
@ -117,14 +117,50 @@ export function NoteContent({
|
|||||||
function NostrMention({ pubkey }: { pubkey: string }) {
|
function NostrMention({ pubkey }: { pubkey: string }) {
|
||||||
const author = useAuthor(pubkey);
|
const author = useAuthor(pubkey);
|
||||||
const npub = nip19.npubEncode(pubkey);
|
const npub = nip19.npubEncode(pubkey);
|
||||||
const displayName = author.data?.metadata?.name ?? npub.slice(0, 8);
|
const hasRealName = !!author.data?.metadata?.name;
|
||||||
|
const displayName = author.data?.metadata?.name ?? generateDeterministicName(pubkey);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
to={`/${npub}`}
|
to={`/${npub}`}
|
||||||
className="font-medium text-blue-500 hover:underline"
|
className={cn(
|
||||||
|
"font-medium hover:underline",
|
||||||
|
hasRealName
|
||||||
|
? "text-blue-500"
|
||||||
|
: "text-gray-500 hover:text-gray-700"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
@{displayName}
|
@{displayName}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a deterministic name based on pubkey
|
||||||
|
function generateDeterministicName(pubkey: string): string {
|
||||||
|
// Use a simple hash of the pubkey to generate consistent adjective + noun combinations
|
||||||
|
const adjectives = [
|
||||||
|
'Swift', 'Bright', 'Calm', 'Bold', 'Wise', 'Kind', 'Quick', 'Brave',
|
||||||
|
'Cool', 'Sharp', 'Clear', 'Strong', 'Smart', 'Fast', 'Keen', 'Pure',
|
||||||
|
'Noble', 'Gentle', 'Fierce', 'Steady', 'Clever', 'Proud', 'Silent', 'Wild'
|
||||||
|
];
|
||||||
|
|
||||||
|
const nouns = [
|
||||||
|
'Fox', 'Eagle', 'Wolf', 'Bear', 'Lion', 'Tiger', 'Hawk', 'Owl',
|
||||||
|
'Deer', 'Raven', 'Falcon', 'Lynx', 'Otter', 'Whale', 'Shark', 'Dolphin',
|
||||||
|
'Phoenix', 'Dragon', 'Panther', 'Jaguar', 'Cheetah', 'Leopard', 'Puma', 'Cobra'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Create a simple hash from the pubkey
|
||||||
|
let hash = 0;
|
||||||
|
for (let i = 0; i < pubkey.length; i++) {
|
||||||
|
const char = pubkey.charCodeAt(i);
|
||||||
|
hash = ((hash << 5) - hash) + char;
|
||||||
|
hash = hash & hash; // Convert to 32-bit integer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use absolute value to ensure positive index
|
||||||
|
const adjIndex = Math.abs(hash) % adjectives.length;
|
||||||
|
const nounIndex = Math.abs(hash >> 8) % nouns.length;
|
||||||
|
|
||||||
|
return `${adjectives[adjIndex]}${nouns[nounIndex]}`;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user