nostr-components 0.2.7 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -186
- package/dist/assets/{base-styles-BSEzBDsk.js → base-styles-Dmuzg8I4.js} +2 -2
- package/dist/assets/{base-styles-BSEzBDsk.js.map → base-styles-Dmuzg8I4.js.map} +1 -1
- package/dist/assets/{copy-delegation-B7y2q5Kn.js → copy-delegation-xzt-t_do.js} +2 -2
- package/dist/assets/{copy-delegation-B7y2q5Kn.js.map → copy-delegation-xzt-t_do.js.map} +1 -1
- package/dist/assets/dialog-component-Da1ZIYh9.js.map +1 -1
- package/dist/assets/{dialog-likers-BqDn2P_3.js → dialog-likers-B15m_NxI.js} +5 -5
- package/dist/assets/dialog-likers-B15m_NxI.js.map +1 -0
- package/dist/assets/index.esm-ByUtE_cm.js +2159 -0
- package/dist/assets/index.esm-ByUtE_cm.js.map +1 -0
- package/dist/assets/nip05-utils-BNBHUmkr.js.map +1 -1
- package/dist/assets/nostr-login-service-D2FmscPI.js +2 -0
- package/dist/assets/nostr-login-service-D2FmscPI.js.map +1 -0
- package/dist/assets/nostr-service-CA0Qx4nJ.js +266 -0
- package/dist/assets/nostr-service-CA0Qx4nJ.js.map +1 -0
- package/dist/assets/{nostr-user-component-Cbs97dlK.js → nostr-user-component-r-MUbTL6.js} +2 -2
- package/dist/assets/{nostr-user-component-Cbs97dlK.js.map → nostr-user-component-r-MUbTL6.js.map} +1 -1
- package/dist/assets/{pure-DPo-pzxM.js → pure-DOoUcNQv.js} +2 -2
- package/dist/assets/pure-DOoUcNQv.js.map +1 -0
- package/dist/assets/theme-BN1Bvweb.js.map +1 -1
- package/dist/assets/{user-resolver-CMmbtY9Y.js → user-resolver-ArI0680e.js} +2 -2
- package/dist/assets/{user-resolver-CMmbtY9Y.js.map → user-resolver-ArI0680e.js.map} +1 -1
- package/dist/assets/utils--bxLbhGF.js.map +1 -1
- package/dist/assets/zap-utils-QRxLBOst.js +2 -0
- package/dist/assets/zap-utils-QRxLBOst.js.map +1 -0
- package/dist/components/nostr-comment.es.js +26 -26
- package/dist/components/nostr-comment.es.js.map +1 -1
- package/dist/components/nostr-dm.es.js +2 -2
- package/dist/components/nostr-dm.es.js.map +1 -1
- package/dist/components/nostr-follow-button.es.js +6 -7
- package/dist/components/nostr-follow-button.es.js.map +1 -1
- package/dist/components/nostr-like.es.js +16 -16
- package/dist/components/nostr-like.es.js.map +1 -1
- package/dist/components/nostr-live-chat.es.js +3 -3
- package/dist/components/nostr-live-chat.es.js.map +1 -1
- package/dist/components/nostr-post.es.js +19 -19
- package/dist/components/nostr-post.es.js.map +1 -1
- package/dist/components/nostr-profile-badge.es.js +2 -2
- package/dist/components/nostr-profile-badge.es.js.map +1 -1
- package/dist/components/nostr-profile.es.js +5 -5
- package/dist/components/nostr-profile.es.js.map +1 -1
- package/dist/components/nostr-zap.es.js +24 -24
- package/dist/components/nostr-zap.es.js.map +1 -1
- package/dist/nostr-components.es.js +1 -1
- package/dist/nostr-components.es.js.map +1 -1
- package/dist/nostr-components.umd.js +2669 -301
- package/dist/nostr-components.umd.js.map +1 -1
- package/dist/src/common/constants.d.ts +1 -1
- package/dist/src/common/nostr-login-service.d.ts +26 -0
- package/dist/src/nostr-dm/nostr-dm.d.ts +1 -1
- package/dist/src/nostr-like/like-utils.d.ts +2 -6
- package/dist/src/nostr-live-chat/nostr-live-chat.d.ts +1 -1
- package/dist/src/nostr-zap/zap-utils.d.ts +4 -0
- package/package.json +5 -2
- package/dist/assets/dialog-likers-BqDn2P_3.js.map +0 -1
- package/dist/assets/nostr-service-CnaPxjc6.js +0 -78
- package/dist/assets/nostr-service-CnaPxjc6.js.map +0 -1
- package/dist/assets/pure-DPo-pzxM.js.map +0 -1
- package/dist/assets/zap-utils-KFUD_vTU.js +0 -2
- package/dist/assets/zap-utils-KFUD_vTU.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const DEFAULT_RELAYS: readonly ["wss://relay.damus.io", "wss://nostr.wine", "wss://relay.nostr.net", "wss://
|
|
1
|
+
export declare const DEFAULT_RELAYS: readonly ["wss://relay.damus.io", "wss://nostr.wine", "wss://relay.nostr.net", "wss://nos.lol", "wss://nostr-pub.wellorder.net", "wss://relay.getalby.com", "wss://relay.primal.net"];
|
|
2
2
|
export declare const MILLISATS_PER_SAT = 1000;
|
|
3
3
|
export declare const NPUB_LENGTH = 63;
|
|
4
4
|
export declare const DEFAULT_PROFILE_IMAGE = "./assets/default_dp.png";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensures NostrLogin is initialized.
|
|
3
|
+
* This will lazy-load the nostr-login package and initialize it on first call.
|
|
4
|
+
* Subsequent calls will return the same promise.
|
|
5
|
+
*
|
|
6
|
+
* @returns Promise that resolves when NostrLogin is initialized
|
|
7
|
+
*/
|
|
8
|
+
export declare function ensureInitialized(): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Check if NostrLogin is available (window.nostr exists)
|
|
11
|
+
* @returns boolean indicating if window.nostr is available
|
|
12
|
+
*/
|
|
13
|
+
export declare function isAvailable(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Get the public key from window.nostr
|
|
16
|
+
* This will trigger NostrLogin auth flow if user isn't authenticated
|
|
17
|
+
* @returns Promise resolving to public key or null
|
|
18
|
+
*/
|
|
19
|
+
export declare function getPublicKey(): Promise<string | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Sign an event using window.nostr
|
|
22
|
+
* This will trigger NostrLogin auth flow if user isn't authenticated
|
|
23
|
+
* @param event - The event to sign
|
|
24
|
+
* @returns Promise resolving to signed event
|
|
25
|
+
*/
|
|
26
|
+
export declare function signEvent(event: any): Promise<any>;
|
|
@@ -17,7 +17,7 @@ export default class NostrDm extends HTMLElement {
|
|
|
17
17
|
private boundHandleSend;
|
|
18
18
|
private boundHandleTextareaChange;
|
|
19
19
|
constructor();
|
|
20
|
-
getRelays: () => readonly ["wss://relay.damus.io", "wss://nostr.wine", "wss://relay.nostr.net", "wss://
|
|
20
|
+
getRelays: () => readonly ["wss://relay.damus.io", "wss://nostr.wine", "wss://relay.nostr.net", "wss://nos.lol", "wss://nostr-pub.wellorder.net", "wss://relay.getalby.com", "wss://relay.primal.net"] | string[];
|
|
21
21
|
getTheme: () => Promise<void>;
|
|
22
22
|
getRecipient: () => void;
|
|
23
23
|
connectedCallback(): void;
|
|
@@ -39,14 +39,10 @@ export declare function createUnlikeEvent(url: string): any;
|
|
|
39
39
|
*/
|
|
40
40
|
export declare function hasUserLiked(url: string, userPubkey: string, relays: string[]): Promise<boolean>;
|
|
41
41
|
/**
|
|
42
|
-
* Get user's pubkey from
|
|
42
|
+
* Get user's pubkey from NostrLogin
|
|
43
43
|
*/
|
|
44
44
|
export declare function getUserPubkey(): Promise<string | null>;
|
|
45
45
|
/**
|
|
46
|
-
* Sign event with
|
|
46
|
+
* Sign event with NostrLogin
|
|
47
47
|
*/
|
|
48
48
|
export declare function signEvent(event: any): Promise<any>;
|
|
49
|
-
/**
|
|
50
|
-
* Check if NIP-07 extension is available
|
|
51
|
-
*/
|
|
52
|
-
export declare function isNip07Available(): boolean;
|
|
@@ -40,7 +40,7 @@ export default class NostrLiveChat extends HTMLElement {
|
|
|
40
40
|
private boundHandleNpubKeydown;
|
|
41
41
|
private resubscribeTimer;
|
|
42
42
|
constructor();
|
|
43
|
-
getRelays: () => readonly ["wss://relay.damus.io", "wss://nostr.wine", "wss://relay.nostr.net", "wss://
|
|
43
|
+
getRelays: () => readonly ["wss://relay.damus.io", "wss://nostr.wine", "wss://relay.nostr.net", "wss://nos.lol", "wss://nostr-pub.wellorder.net", "wss://relay.getalby.com", "wss://relay.primal.net"] | string[];
|
|
44
44
|
private getCurrentUserInfo;
|
|
45
45
|
private getDisplayType;
|
|
46
46
|
getTheme: () => void;
|
|
@@ -16,6 +16,10 @@ export declare const fetchInvoice: ({ zapEndpoint, amount, comment, authorId, ni
|
|
|
16
16
|
anon?: boolean;
|
|
17
17
|
url?: string;
|
|
18
18
|
}) => Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if NostrLogin is available
|
|
21
|
+
* @deprecated Use ensureInitialized() instead - it will initialize NostrLogin if needed
|
|
22
|
+
*/
|
|
19
23
|
export declare const isNip07ExtAvailable: () => boolean;
|
|
20
24
|
export declare function resolveNip05(nip05Identifier: string): Promise<string | null>;
|
|
21
25
|
declare module 'nostr-tools' {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nostr-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Embed Nostr anywhere on the internet, a Zap Button for every webpage",
|
|
6
6
|
"keywords": [
|
|
@@ -99,7 +99,9 @@
|
|
|
99
99
|
"storybook": "storybook dev -p 6006",
|
|
100
100
|
"build-storybook": "cross-env STORYBOOK_ENV=production storybook build && npm run build:themes",
|
|
101
101
|
"wp-build": "npm run build:esm && npm run build:themes && npm run wp-copy",
|
|
102
|
-
"wp-copy": "node scripts/wp-copy.js"
|
|
102
|
+
"wp-copy": "node scripts/wp-copy.js",
|
|
103
|
+
"wp-prepare-svn": "node scripts/prepare-svn.js",
|
|
104
|
+
"wp-release": "npm run wp-build && npm run wp-prepare-svn"
|
|
103
105
|
},
|
|
104
106
|
"devDependencies": {
|
|
105
107
|
"@chromatic-com/storybook": "^4.1.1",
|
|
@@ -126,6 +128,7 @@
|
|
|
126
128
|
"@types/qrcode": "^1.5.5",
|
|
127
129
|
"dompurify": "^3.2.6",
|
|
128
130
|
"light-bolt11-decoder": "^3.2.0",
|
|
131
|
+
"nostr-login": "^1.7.12",
|
|
129
132
|
"nostr-tools": "^2.7.2",
|
|
130
133
|
"qrcode": "^1.5.4"
|
|
131
134
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"mappings":"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","names":["getLikersDialogStyles","theme","isDark","injectLikersDialogStyles","style","renderLikeEntry","like","index","authorNameSafe","escapeHtml","njumpUrl","hexToNpub","profilePictureSafe","isValidUrl","profilePicture","isDislike","statusText","statusClass","formatRelativeTime","renderSkeletonLikeEntry","npub","openLikersDialog","params","likeDetails","dialogComponent","initialContent","renderInitialContent","dialogElement","_a","dialog","enhanceLikeDetailsProgressively","npubs","likersList","uniqueAuthorIds","profileResults","getBatchedProfileMetadata","profileMap","result","npubMap","pubkey","profile","enhanced","profileContent","extractProfileMetadataContent","skeletonEntry","enhancedEntry","error","enhanceLikeDetailsIndividually","profileCache","profilePromises","cachedProfile","getProfileMetadata","__vitePreload","profileMetadata","promise"],"ignoreList":[],"sources":["../../src/nostr-like/dialog-likers-style.ts","../../src/nostr-like/dialog-likers.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nexport function getLikersDialogStyles(theme: 'light' | 'dark' = 'light'): string {\n const isDark = theme === 'dark';\n \n return `\n .likers-dialog-content {\n padding: 0;\n max-height: 60vh;\n overflow-y: auto;\n }\n\n .likers-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .like-entry {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 8px;\n background: ${isDark ? '#2a2a2a' : '#f8f9fa'};\n border: 1px solid ${isDark ? '#3a3a3a' : '#e9ecef'};\n transition: background-color 0.2s ease;\n }\n\n .like-entry:hover {\n background: ${isDark ? '#3a3a3a' : '#e9ecef'};\n }\n\n .like-author-info {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n }\n\n .like-author-picture {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n object-fit: cover;\n flex-shrink: 0;\n }\n\n .like-author-picture-default {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: ${isDark ? '#3a3a3a' : '#e9ecef'};\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n flex-shrink: 0;\n }\n\n .like-author-details {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n min-width: 0;\n }\n\n .like-author-link {\n color: ${isDark ? '#ffffff' : '#000000'};\n text-decoration: none;\n font-weight: 500;\n font-size: 14px;\n transition: color 0.2s ease;\n }\n\n .like-author-link:hover {\n color: ${isDark ? '#4a9eff' : '#1877f2'};\n text-decoration: underline;\n }\n\n .like-date {\n color: ${isDark ? '#b0b0b0' : '#65676b'};\n font-size: 12px;\n font-weight: 400;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .like-status {\n font-weight: 500;\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 4px;\n }\n\n .like-status.liked {\n color: ${isDark ? '#4a9eff' : '#1877f2'};\n background: ${isDark ? 'rgba(74, 158, 255, 0.1)' : 'rgba(24, 119, 242, 0.1)'};\n }\n\n .like-status.disliked {\n color: #d32f2f;\n background: rgba(211, 47, 47, 0.1);\n }\n\n .no-likes {\n text-align: center;\n color: ${isDark ? '#b0b0b0' : '#65676b'};\n font-size: 14px;\n padding: 40px 20px;\n }\n\n /* Skeleton loading states */\n .skeleton-entry {\n opacity: 0.7;\n }\n\n .skeleton-picture {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(90deg, \n ${isDark ? '#3a3a3a' : '#f0f0f0'} 25%, \n ${isDark ? '#4a4a4a' : '#e0e0e0'} 50%, \n ${isDark ? '#3a3a3a' : '#f0f0f0'} 75%\n );\n background-size: 200% 100%;\n animation: skeleton-loading 1.5s infinite;\n flex-shrink: 0;\n }\n\n .skeleton-name {\n width: 120px;\n height: 14px;\n background: linear-gradient(90deg, \n ${isDark ? '#3a3a3a' : '#f0f0f0'} 25%, \n ${isDark ? '#4a4a4a' : '#e0e0e0'} 50%, \n ${isDark ? '#3a3a3a' : '#f0f0f0'} 75%\n );\n background-size: 200% 100%;\n animation: skeleton-loading 1.5s infinite;\n border-radius: 2px;\n }\n\n @keyframes skeleton-loading {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n }\n\n /* Responsive */\n @media (max-width: 480px) {\n .likers-dialog-content {\n max-height: 70vh;\n }\n\n .like-entry {\n padding: 10px;\n }\n\n .like-author-picture,\n .like-author-picture-default,\n .skeleton-picture {\n width: 36px;\n height: 36px;\n }\n\n .like-author-link {\n font-size: 13px;\n }\n\n .like-date {\n font-size: 11px;\n }\n }\n\n /* Scrollbar styling */\n .likers-dialog-content::-webkit-scrollbar {\n width: 6px;\n }\n\n .likers-dialog-content::-webkit-scrollbar-track {\n background: ${isDark ? '#2a2a2a' : '#f1f1f1'};\n border-radius: 3px;\n }\n\n .likers-dialog-content::-webkit-scrollbar-thumb {\n background: ${isDark ? '#555' : '#c1c1c1'};\n border-radius: 3px;\n }\n\n .likers-dialog-content::-webkit-scrollbar-thumb:hover {\n background: ${isDark ? '#777' : '#a8a8a8'};\n }\n `;\n}\n","// SPDX-License-Identifier: MIT\n\n// Import for side effects to register the custom element\nimport '../base/dialog-component/dialog-component';\nimport type { DialogComponent } from '../base/dialog-component/dialog-component';\nimport { getLikersDialogStyles } from './dialog-likers-style';\nimport { getBatchedProfileMetadata, extractProfileMetadataContent } from '../nostr-zap/zap-utils';\nimport { escapeHtml, formatRelativeTime, hexToNpub, isValidUrl } from '../common/utils';\nimport { LikeDetails } from './like-utils';\n\n/**\n * Modal dialog for displaying individual like details (likers).\n * \n * Shows a list of all users who liked a URL with:\n * - User's name\n * - User's profile picture\n * - Time of like (relative time)\n * - Clickable links to user profiles via njump.me\n */\n\nexport interface OpenLikersModalParams {\n likeDetails: LikeDetails[];\n theme?: 'light' | 'dark';\n}\n\n/**\n * Inject likers dialog content styles into document head\n * Prevents duplicate injection by checking for existing styles\n */\nexport const injectLikersDialogStyles = (theme: 'light' | 'dark' = 'light') => {\n // Remove existing likers dialog styles\n const existingStyles = document.querySelectorAll('style[data-likers-dialog-styles]');\n existingStyles.forEach(style => style.remove());\n \n const style = document.createElement('style');\n style.setAttribute('data-likers-dialog-styles', 'true');\n style.textContent = getLikersDialogStyles(theme);\n document.head.appendChild(style);\n}\n\ninterface EnhancedLikeDetails extends LikeDetails {\n authorName?: string;\n authorPicture?: string;\n authorNpub?: string;\n}\n\n/**\n * Render individual like entry HTML (with profile data)\n */\nfunction renderLikeEntry(like: EnhancedLikeDetails, index: number): string {\n const authorNameSafe = escapeHtml(like.authorName || 'Unknown liker');\n const npubSafe = like.authorNpub || hexToNpub(like.authorPubkey);\n const njumpUrl = `https://njump.me/${npubSafe}`;\n const profilePictureSafe = isValidUrl(like.authorPicture || '') ? like.authorPicture || '' : '';\n \n const profilePicture = profilePictureSafe \n ? `<img src=\"${profilePictureSafe}\" alt=\"${authorNameSafe}\" class=\"like-author-picture\" />`\n : `<div class=\"like-author-picture-default\">👤</div>`;\n \n const isDislike = like.content === '-';\n const statusText = isDislike ? 'Disliked' : 'Liked';\n const statusClass = isDislike ? 'disliked' : 'liked';\n \n return `\n <div class=\"like-entry\" data-like-index=\"${index}\" data-author-pubkey=\"${like.authorPubkey}\">\n <div class=\"like-author-info\">\n ${profilePicture}\n <div class=\"like-author-details\">\n <a href=\"${njumpUrl}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"like-author-link\">\n ${authorNameSafe}\n </a>\n <div class=\"like-date\">\n ${formatRelativeTime(Math.floor(like.date.getTime() / 1000))}\n <span class=\"like-status ${statusClass}\">${statusText}</span>\n </div>\n </div>\n </div>\n </div>\n `;\n}\n\n/**\n * Render skeleton like entry HTML (with npub)\n */\nfunction renderSkeletonLikeEntry(like: LikeDetails, npub: string, index: number): string {\n const isDislike = like.content === '-';\n const statusText = isDislike ? 'Disliked' : 'Liked';\n const statusClass = isDislike ? 'disliked' : 'liked';\n \n return `\n <div class=\"like-entry skeleton-entry\" data-like-index=\"${index}\" data-author-pubkey=\"${like.authorPubkey}\">\n <div class=\"like-author-info\">\n <div class=\"skeleton-picture\"></div>\n <div class=\"like-author-details\">\n <div class=\"like-author-link skeleton-name\">\n ${escapeHtml(npub)}\n </div>\n <div class=\"like-date\">\n ${formatRelativeTime(Math.floor(like.date.getTime() / 1000))}\n <span class=\"like-status ${statusClass}\">${statusText}</span>\n </div>\n </div>\n </div>\n </div>\n `;\n}\n\n/**\n * Opens the likers dialog showing individual like details\n */\nexport async function openLikersDialog(params: OpenLikersModalParams): Promise<DialogComponent> {\n const { likeDetails, theme = 'light' } = params;\n \n // Inject styles\n injectLikersDialogStyles(theme);\n \n // Ensure custom element is defined\n if (!customElements.get('dialog-component')) {\n await customElements.whenDefined('dialog-component');\n }\n \n // Create dialog component (not added to DOM)\n const dialogComponent = document.createElement('dialog-component') as DialogComponent;\n dialogComponent.setAttribute('header', 'Likers');\n if (params.theme) {\n dialogComponent.setAttribute('data-theme', params.theme);\n }\n \n // Initial content with skeleton loaders showing npubs\n const initialContent = await renderInitialContent(likeDetails);\n dialogComponent.innerHTML = initialContent;\n \n // Show the dialog (this will create and append the actual dialog element)\n dialogComponent.showModal();\n \n // Get the actual dialog element for progressive enhancement\n const dialogElement: HTMLDialogElement | null = \n dialogComponent.querySelector('.nostr-base-dialog') ||\n dialogComponent.shadowRoot?.querySelector('.nostr-base-dialog') ||\n document.body.querySelector('.nostr-base-dialog');\n \n if (!dialogElement) {\n console.error('[openLikersDialog] Failed to find dialog element after showModal()');\n throw new Error('Dialog element not found. The dialog may not have been created properly.');\n }\n \n // Type assertion: dialog is guaranteed to be non-null after the check above\n const dialog = dialogElement as HTMLDialogElement;\n \n // Start progressive enhancement\n if (dialog && likeDetails.length > 0) {\n enhanceLikeDetailsProgressively(dialog, likeDetails);\n }\n\n return dialogComponent;\n}\n\n/**\n * Render initial dialog content with skeleton loaders showing npubs\n */\nasync function renderInitialContent(likeDetails: LikeDetails[]): Promise<string> {\n if (likeDetails.length === 0) {\n return `\n <div class=\"likers-dialog-content\">\n <div class=\"likers-list\">\n <div class=\"no-likes\">No likes yet</div>\n </div>\n </div>\n `;\n }\n\n // Convert all pubkeys to npubs for immediate display\n const npubs = likeDetails.map(like => hexToNpub(like.authorPubkey));\n\n const skeletonEntries = likeDetails.map((like, index) => \n renderSkeletonLikeEntry(like, npubs[index], index)\n ).join('');\n\n return `\n <div class=\"likers-dialog-content\">\n <div class=\"likers-list\">\n ${skeletonEntries}\n </div>\n </div>\n `;\n}\n\n/**\n * Progressively enhance like details with profile information (batched approach)\n */\nasync function enhanceLikeDetailsProgressively(dialog: HTMLDialogElement, likeDetails: LikeDetails[]): Promise<void> {\n const likersList = dialog.querySelector('.likers-list') as HTMLElement;\n if (!likersList) return;\n\n // Get unique author IDs\n const uniqueAuthorIds = [...new Set(likeDetails.map(like => like.authorPubkey))];\n console.log(\"Nostr-Components: Likers dialog: Fetching profiles for\", uniqueAuthorIds.length, \"unique authors\");\n\n try {\n // Fetch all profiles in a single batched call\n const profileResults = await getBatchedProfileMetadata(uniqueAuthorIds);\n \n // Create a map for quick lookup\n const profileMap = new Map<string, any>();\n profileResults.forEach(result => {\n profileMap.set(result.id, result.profile);\n });\n\n // Convert all pubkeys to npubs for display\n const npubMap = new Map<string, string>();\n uniqueAuthorIds.forEach(pubkey => {\n npubMap.set(pubkey, hexToNpub(pubkey));\n });\n\n // Process each like entry\n for (let index = 0; index < likeDetails.length; index++) {\n const like = likeDetails[index];\n const profile = profileMap.get(like.authorPubkey);\n const npub = npubMap.get(like.authorPubkey) || like.authorPubkey;\n \n let enhanced: EnhancedLikeDetails;\n \n if (profile) {\n const profileContent = extractProfileMetadataContent(profile);\n enhanced = {\n ...like,\n authorName: profileContent.display_name || profileContent.name || npub,\n authorPicture: profileContent.picture,\n authorNpub: npub,\n };\n } else {\n // Fallback if profile not found\n enhanced = {\n ...like,\n authorName: npub,\n authorNpub: npub,\n };\n }\n\n // Find the corresponding skeleton entry by index and replace it\n const skeletonEntry = likersList.querySelector(`[data-like-index=\"${index}\"]`);\n if (skeletonEntry) {\n const enhancedEntry = renderLikeEntry(enhanced, index);\n skeletonEntry.outerHTML = enhancedEntry;\n }\n }\n\n console.log(\"Nostr-Components: Likers dialog: Progressive enhancement completed for\", likeDetails.length, \"like entries\");\n } catch (error) {\n console.error(\"Nostr-Components: Likers dialog: Error in batched profile enhancement\", error);\n \n // Fallback to individual processing if batched approach fails\n console.log(\"Nostr-Components: Likers dialog: Falling back to individual profile fetching\");\n await enhanceLikeDetailsIndividually(dialog, likeDetails);\n }\n}\n\n/**\n * Fallback: Enhance like details individually (original approach)\n */\nasync function enhanceLikeDetailsIndividually(dialog: HTMLDialogElement, likeDetails: LikeDetails[]): Promise<void> {\n const likersList = dialog.querySelector('.likers-list') as HTMLElement;\n if (!likersList) return;\n\n // Create a map to track which profiles we've already fetched\n const profileCache = new Map<string, EnhancedLikeDetails>();\n \n // Fetch all profile metadata in parallel\n const profilePromises = likeDetails.map(async (like, index) => {\n // Check if we already have this profile cached\n if (profileCache.has(like.authorPubkey)) {\n const cachedProfile = profileCache.get(like.authorPubkey)!;\n return {\n index,\n enhanced: {\n ...like,\n authorName: cachedProfile.authorName,\n authorPicture: cachedProfile.authorPicture,\n authorNpub: cachedProfile.authorNpub,\n }\n };\n }\n\n try {\n const { getProfileMetadata } = await import('../nostr-zap/zap-utils');\n const profileMetadata = await getProfileMetadata(like.authorPubkey);\n const profileContent = extractProfileMetadataContent(profileMetadata);\n const npub = hexToNpub(like.authorPubkey);\n \n const enhanced = {\n ...like,\n authorName: profileContent.display_name || profileContent.name || npub,\n authorPicture: profileContent.picture,\n authorNpub: npub,\n };\n\n // Cache the profile for other entries from the same author\n profileCache.set(like.authorPubkey, enhanced);\n \n return {\n index,\n enhanced\n };\n } catch (error) {\n console.error(\"Nostr-Components: Likers dialog: Error fetching profile for\", like.authorPubkey, error);\n // Fallback with just pubkey converted to npub\n const npub = hexToNpub(like.authorPubkey);\n const enhanced = {\n ...like,\n authorName: npub,\n authorNpub: npub,\n };\n \n // Cache the fallback profile\n profileCache.set(like.authorPubkey, enhanced);\n \n return {\n index,\n enhanced\n };\n }\n });\n\n // Process each profile as it becomes available\n for (const promise of profilePromises) {\n try {\n const { index, enhanced } = await promise;\n \n // Find the corresponding skeleton entry by index and replace it\n const skeletonEntry = likersList.querySelector(`[data-like-index=\"${index}\"]`);\n if (skeletonEntry) {\n const enhancedEntry = renderLikeEntry(enhanced, index);\n skeletonEntry.outerHTML = enhancedEntry;\n }\n } catch (error) {\n console.error(\"Nostr-Components: Likers dialog: Error processing profile enhancement\", error);\n }\n }\n}\n"],"file":"assets/dialog-likers-BqDn2P_3.js"}
|