diff --git a/dist/index.html b/dist/index.html index 971caa06..dc5b4fa9 100644 --- a/dist/index.html +++ b/dist/index.html @@ -5,7 +5,7 @@ Boris - Nostr Bookmarks - + diff --git a/src/components/Bookmarks.tsx b/src/components/Bookmarks.tsx index 780cf0b0..b0d4666f 100644 --- a/src/components/Bookmarks.tsx +++ b/src/components/Bookmarks.tsx @@ -7,7 +7,7 @@ import { Bookmark } from '../types/bookmarks' import { Highlight } from '../types/highlights' import { BookmarkList } from './BookmarkList' import { fetchBookmarks } from '../services/bookmarkService' -import { fetchHighlights, fetchHighlightsForArticle } from '../services/highlightService' +import { fetchHighlights, fetchHighlightsForArticle, fetchHighlightsForUrl } from '../services/highlightService' import { fetchContacts } from '../services/contactService' import ContentPanel from './ContentPanel' import { HighlightsPanel } from './HighlightsPanel' @@ -225,15 +225,23 @@ const Bookmarks: React.FC = ({ relayPool, onLogout }) => { const handleHighlightCreated = async () => { // Refresh highlights after creating a new one - if (!relayPool || !currentArticleCoordinate) return + if (!relayPool) return try { - const newHighlights = await fetchHighlightsForArticle( - relayPool, - currentArticleCoordinate, - currentArticleEventId - ) - setHighlights(newHighlights) + // Refresh based on what we're currently viewing + if (currentArticleCoordinate) { + // Viewing a nostr article - fetch by article coordinate + const newHighlights = await fetchHighlightsForArticle( + relayPool, + currentArticleCoordinate, + currentArticleEventId + ) + setHighlights(newHighlights) + } else if (selectedUrl && !selectedUrl.startsWith('nostr:')) { + // Viewing an external URL - fetch by URL + const newHighlights = await fetchHighlightsForUrl(relayPool, selectedUrl) + setHighlights(newHighlights) + } } catch (err) { console.error('Failed to refresh highlights:', err) } @@ -248,17 +256,32 @@ const Bookmarks: React.FC = ({ relayPool, onLogout }) => { }, []) const handleCreateHighlight = useCallback(async (text: string) => { - if (!activeAccount || !relayPool || !currentArticle) { + if (!activeAccount || !relayPool) { console.error('Missing requirements for highlight creation') return } + // Need either a nostr article or an external URL + if (!currentArticle && !selectedUrl) { + console.error('No source available for highlight creation') + return + } + try { + // Determine the source: prefer currentArticle (for nostr content), fallback to selectedUrl (for external URLs) + const source = currentArticle || selectedUrl! + + // For context extraction, use article content or reader content + const contentForContext = currentArticle + ? currentArticle.content + : readerContent?.markdown || readerContent?.html + await createHighlight( text, - currentArticle, + source, activeAccount, - relayPool + relayPool, + contentForContext ) console.log('✅ Highlight created successfully!') @@ -269,7 +292,7 @@ const Bookmarks: React.FC = ({ relayPool, onLogout }) => { } catch (error) { console.error('Failed to create highlight:', error) } - }, [activeAccount, relayPool, currentArticle, handleHighlightCreated]) + }, [activeAccount, relayPool, currentArticle, selectedUrl, readerContent, handleHighlightCreated]) return ( <> diff --git a/src/services/highlightCreationService.ts b/src/services/highlightCreationService.ts index ebeaaa84..2afd0a5a 100644 --- a/src/services/highlightCreationService.ts +++ b/src/services/highlightCreationService.ts @@ -8,32 +8,45 @@ import { RELAYS } from '../config/relays' /** * Creates and publishes a highlight event (NIP-84) + * Supports both nostr-native articles and external URLs */ export async function createHighlight( selectedText: string, - article: NostrEvent | null, + source: NostrEvent | string, account: IAccount, relayPool: RelayPool, + contentForContext?: string, comment?: string ): Promise { - if (!selectedText || !article) { + if (!selectedText || !source) { throw new Error('Missing required data to create highlight') } // Create EventFactory with the account as signer const factory = new EventFactory({ signer: account }) - // Parse article coordinate to get address pointer - const addressPointer = parseArticleCoordinate(article) + let blueprintSource: NostrEvent | AddressPointer | string + let context: string | undefined - // Extract context (previous and next sentences from the same paragraph) - const context = extractContext(selectedText, article.content) + // Handle NostrEvent (article) source + if (typeof source === 'object' && 'kind' in source) { + blueprintSource = parseArticleCoordinate(source) + context = extractContext(selectedText, source.content) + } + // Handle URL string source + else { + blueprintSource = source + // Try to extract context from provided content if available + if (contentForContext) { + context = extractContext(selectedText, contentForContext) + } + } // Create highlight event using the blueprint const highlightEvent = await factory.create( HighlightBlueprint, selectedText, - addressPointer, + blueprintSource, context ? { comment, context } : comment ? { comment } : undefined )