From 5ceaced77142353821723fe3642fad5ca8251af8 Mon Sep 17 00:00:00 2001 From: silberengel Date: Fri, 18 Jul 2025 08:17:50 +0200 Subject: [PATCH] ran prettier --- src/app.css | 2 +- src/lib/components/CommentBox.svelte | 233 +++++--- src/lib/components/EventDetails.svelte | 188 +++--- src/lib/components/EventInput.svelte | 330 +++++++---- src/lib/components/EventSearch.svelte | 302 +++++++--- src/lib/components/LoginMenu.svelte | 228 +++++--- src/lib/components/LoginModal.svelte | 22 +- src/lib/components/Preview.svelte | 4 +- src/lib/components/ZettelEditor.svelte | 100 ++-- src/lib/components/cards/BlogHeader.svelte | 2 - src/lib/components/cards/ProfileHeader.svelte | 32 +- .../publications/Publication.svelte | 30 +- .../publications/PublicationFeed.svelte | 51 +- .../publications/PublicationHeader.svelte | 59 +- .../publications/PublicationSection.svelte | 111 ++-- .../publications/TableOfContents.svelte | 42 +- .../svelte_publication_tree.svelte.ts | 14 +- .../publications/table_of_contents.svelte.ts | 67 ++- src/lib/components/util/ArticleNav.svelte | 92 +-- src/lib/components/util/CardActions.svelte | 50 +- .../components/util/ContainingIndexes.svelte | 10 +- src/lib/components/util/Details.svelte | 57 +- src/lib/components/util/Profile.svelte | 21 +- .../util/ViewPublicationLink.svelte | 17 +- src/lib/consts.ts | 6 +- src/lib/data_structures/publication_tree.ts | 209 ++++--- .../EventNetwork/utils/networkBuilder.ts | 11 +- src/lib/ndk.ts | 65 +- src/lib/services/publisher.ts | 66 ++- src/lib/snippets/UserSnippets.svelte | 46 +- src/lib/stores.ts | 13 +- src/lib/stores/authStore.Svelte.ts | 4 +- src/lib/stores/userStore.ts | 193 +++--- src/lib/utils/ZettelParser.ts | 103 ++-- src/lib/utils/community_checker.ts | 52 +- src/lib/utils/event_input_utils.ts | 252 ++++---- src/lib/utils/indexEventCache.ts | 38 +- .../advancedAsciidoctorPostProcessor.ts | 10 +- src/lib/utils/markup/advancedMarkupParser.ts | 39 +- .../utils/markup/asciidoctorPostProcessor.ts | 13 +- src/lib/utils/markup/basicMarkupParser.ts | 6 +- src/lib/utils/mime.ts | 19 +- src/lib/utils/nostrEventService.ts | 246 ++++---- src/lib/utils/nostrUtils.ts | 136 +++-- src/lib/utils/profile_search.ts | 331 ++++++----- src/lib/utils/relayDiagnostics.ts | 64 +- src/lib/utils/searchCache.ts | 16 +- src/lib/utils/search_constants.ts | 46 +- src/lib/utils/search_types.ts | 8 +- src/lib/utils/search_utility.ts | 32 +- src/lib/utils/search_utils.ts | 37 +- src/lib/utils/subscription_search.ts | 553 ++++++++++++------ src/routes/+layout.ts | 141 +++-- src/routes/+page.svelte | 26 +- src/routes/about/+page.svelte | 8 +- src/routes/contact/+page.svelte | 25 +- src/routes/events/+page.svelte | 324 ++++++---- src/routes/new/compose/+page.svelte | 33 +- src/routes/publication/+page.svelte | 46 +- src/routes/publication/+page.ts | 70 ++- src/routes/start/+page.svelte | 25 +- src/routes/visualize/+page.svelte | 6 +- src/styles/asciidoc.css | 2 +- test_data/LaTeXtestfile.json | 22 +- test_data/LaTeXtestfile.md | 21 +- tests/unit/latexRendering.test.ts | 56 +- 66 files changed, 3398 insertions(+), 2085 deletions(-) diff --git a/src/app.css b/src/app.css index 87577c2..1f07464 100644 --- a/src/app.css +++ b/src/app.css @@ -3,7 +3,7 @@ @import "./styles/publications.css"; @import "./styles/visualize.css"; @import "./styles/events.css"; -@import './styles/asciidoc.css'; +@import "./styles/asciidoc.css"; /* Custom styles */ @layer base { diff --git a/src/lib/components/CommentBox.svelte b/src/lib/components/CommentBox.svelte index c412cb8..5407f72 100644 --- a/src/lib/components/CommentBox.svelte +++ b/src/lib/components/CommentBox.svelte @@ -4,9 +4,12 @@ import { nip19 } from "nostr-tools"; import { toNpub, getUserMetadata } from "$lib/utils/nostrUtils"; import { searchProfiles } from "$lib/utils/search_utility"; - import type { NostrProfile, ProfileSearchResult } from "$lib/utils/search_utility"; + import type { + NostrProfile, + ProfileSearchResult, + } from "$lib/utils/search_utility"; - import { userPubkey } from '$lib/stores/authStore.Svelte'; + import { userPubkey } from "$lib/stores/authStore.Svelte"; import type { NDKEvent } from "$lib/utils/nostrUtils"; import { extractRootEventInfo, @@ -16,7 +19,7 @@ publishEvent, navigateToEvent, } from "$lib/utils/nostrEventService"; - import { tick } from 'svelte'; + import { tick } from "svelte"; import { goto } from "$app/navigation"; const props = $props<{ @@ -36,11 +39,11 @@ // Add state for modals and search let showMentionModal = $state(false); let showWikilinkModal = $state(false); - let mentionSearch = $state(''); + let mentionSearch = $state(""); let mentionResults = $state([]); let mentionLoading = $state(false); - let wikilinkTarget = $state(''); - let wikilinkLabel = $state(''); + let wikilinkTarget = $state(""); + let wikilinkLabel = $state(""); let mentionSearchTimeout: ReturnType | null = null; let mentionSearchInput: HTMLInputElement | undefined; @@ -48,7 +51,7 @@ $effect(() => { if (showMentionModal) { // Reset search when modal opens - mentionSearch = ''; + mentionSearch = ""; mentionResults = []; mentionLoading = false; // Focus the search input after a brief delay to ensure modal is rendered @@ -57,7 +60,7 @@ }, 100); } else { // Reset search when modal closes - mentionSearch = ''; + mentionSearch = ""; mentionResults = []; mentionLoading = false; } @@ -68,12 +71,12 @@ const npub = toNpub(trimmedPubkey); if (npub) { // Call an async function, but don't make the effect itself async - getUserMetadata(npub).then(metadata => { + getUserMetadata(npub).then((metadata) => { userProfile = metadata; }); } else if (trimmedPubkey) { userProfile = null; - error = 'Invalid public key: must be a 64-character hex string.'; + error = "Invalid public key: must be a 64-character hex string."; } else { userProfile = null; error = null; @@ -82,11 +85,10 @@ $effect(() => { if (!success) return; - - content = ''; - preview = ''; - } - ); + + content = ""; + preview = ""; + }); // Markup buttons const markupButtons = [ @@ -99,8 +101,20 @@ { label: "List", action: () => insertMarkup("* ", "") }, { label: "Numbered List", action: () => insertMarkup("1. ", "") }, { label: "Hashtag", action: () => insertMarkup("#", "") }, - { label: '@', action: () => { mentionSearch = ''; mentionResults = []; showMentionModal = true; } }, - { label: 'Wikilink', action: () => { showWikilinkModal = true; } }, + { + label: "@", + action: () => { + mentionSearch = ""; + mentionResults = []; + showMentionModal = true; + }, + }, + { + label: "Wikilink", + action: () => { + showWikilinkModal = true; + }, + }, ]; function insertMarkup(prefix: string, suffix: string) { @@ -162,15 +176,17 @@ success = null; try { - const pk = $userPubkey || ''; + const pk = $userPubkey || ""; const npub = toNpub(pk); - + if (!npub) { - throw new Error('Invalid public key: must be a 64-character hex string.'); + throw new Error( + "Invalid public key: must be a 64-character hex string.", + ); } - + if (props.event.kind === undefined || props.event.kind === null) { - throw new Error('Invalid event: missing kind'); + throw new Error("Invalid event: missing kind"); } const parent = props.event; @@ -185,14 +201,19 @@ const tags = buildReplyTags(parent, rootInfo, parentInfo, kind); // Create and sign the event - const { event: signedEvent } = await createSignedEvent(content, pk, kind, tags); + const { event: signedEvent } = await createSignedEvent( + content, + pk, + kind, + tags, + ); // Publish the event const result = await publishEvent( signedEvent, useOtherRelays, useFallbackRelays, - props.userRelayPreference + props.userRelayPreference, ); if (result.success) { @@ -202,17 +223,19 @@ } else { if (!useOtherRelays && !useFallbackRelays) { showOtherRelays = true; - error = "Failed to publish to primary relays. Would you like to try the other relays?"; + error = + "Failed to publish to primary relays. Would you like to try the other relays?"; } else if (useOtherRelays && !useFallbackRelays) { showFallbackRelays = true; - error = "Failed to publish to other relays. Would you like to try the fallback relays?"; + error = + "Failed to publish to other relays. Would you like to try the fallback relays?"; } else { error = "Failed to publish comment. Please try again later."; } } } catch (e: unknown) { - console.error('Error publishing comment:', e); - error = e instanceof Error ? e.message : 'An unexpected error occurred'; + console.error("Error publishing comment:", e); + error = e instanceof Error ? e.message : "An unexpected error occurred"; } finally { isSubmitting = false; } @@ -220,8 +243,8 @@ // Add a helper to shorten npub function shortenNpub(npub: string | undefined) { - if (!npub) return ''; - return npub.slice(0, 8) + '…' + npub.slice(-4); + if (!npub) return ""; + return npub.slice(0, 8) + "…" + npub.slice(-4); } async function insertAtCursor(text: string) { @@ -233,10 +256,10 @@ content = content.substring(0, start) + text + content.substring(end); updatePreview(); - + // Wait for DOM updates to complete await tick(); - + textarea.focus(); textarea.selectionStart = textarea.selectionEnd = start + text.length; } @@ -244,51 +267,62 @@ // Add mention search functionality using centralized search utility let communityStatus: Record = $state({}); let isSearching = $state(false); - + async function searchMentions() { if (!mentionSearch.trim()) { mentionResults = []; communityStatus = {}; return; } - + // Prevent multiple concurrent searches if (isSearching) { return; } - - console.log('Starting search for:', mentionSearch.trim()); - + + console.log("Starting search for:", mentionSearch.trim()); + // Set loading state mentionLoading = true; isSearching = true; - + try { - console.log('Search promise created, waiting for result...'); + console.log("Search promise created, waiting for result..."); const result = await searchProfiles(mentionSearch.trim()); - console.log('Search completed, found profiles:', result.profiles.length); - console.log('Profile details:', result.profiles); - console.log('Community status:', result.Status); - + console.log("Search completed, found profiles:", result.profiles.length); + console.log("Profile details:", result.profiles); + console.log("Community status:", result.Status); + // Update state mentionResults = result.profiles; communityStatus = result.Status; - - console.log('State updated - mentionResults length:', mentionResults.length); - console.log('State updated - communityStatus keys:', Object.keys(communityStatus)); + + console.log( + "State updated - mentionResults length:", + mentionResults.length, + ); + console.log( + "State updated - communityStatus keys:", + Object.keys(communityStatus), + ); } catch (error) { - console.error('Error searching mentions:', error); + console.error("Error searching mentions:", error); mentionResults = []; communityStatus = {}; } finally { mentionLoading = false; isSearching = false; - console.log('Search finished - loading:', mentionLoading, 'searching:', isSearching); + console.log( + "Search finished - loading:", + mentionLoading, + "searching:", + isSearching, + ); } } function selectMention(profile: NostrProfile) { - let mention = ''; + let mention = ""; if (profile.pubkey) { try { const npub = toNpub(profile.pubkey); @@ -299,22 +333,22 @@ mention = `nostr:${profile.pubkey}`; } } catch (e) { - console.error('Error in toNpub:', e); + console.error("Error in toNpub:", e); // Fallback to pubkey if conversion fails mention = `nostr:${profile.pubkey}`; } } else { - console.warn('No pubkey in profile, falling back to display name'); + console.warn("No pubkey in profile, falling back to display name"); mention = `@${profile.displayName || profile.name}`; } insertAtCursor(mention); showMentionModal = false; - mentionSearch = ''; + mentionSearch = ""; mentionResults = []; } function insertWikilink() { - let markup = ''; + let markup = ""; if (wikilinkLabel.trim()) { markup = `[[${wikilinkTarget}|${wikilinkLabel}]]`; } else { @@ -322,8 +356,8 @@ } insertAtCursor(markup); showWikilinkModal = false; - wikilinkTarget = ''; - wikilinkLabel = ''; + wikilinkTarget = ""; + wikilinkLabel = ""; } function handleViewComment() { @@ -362,15 +396,15 @@ bind:value={mentionSearch} bind:this={mentionSearchInput} onkeydown={(e) => { - if (e.key === 'Enter' && mentionSearch.trim() && !isSearching) { + if (e.key === "Enter" && mentionSearch.trim() && !isSearching) { searchMentions(); } }} class="flex-1 rounded-lg border border-gray-300 bg-gray-50 text-gray-900 text-sm focus:border-primary-500 focus:ring-primary-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-primary-500 dark:focus:ring-primary-500 p-2.5" /> - - + {#if mentionLoading}
Searching...
{:else if mentionResults.length > 0} -
Found {mentionResults.length} results
-
+
+ Found {mentionResults.length} results +
+
    {#each mentionResults as profile} - {/each} @@ -427,7 +497,9 @@ {:else if mentionSearch.trim()}
    No results found
    {:else} -
    Enter a search term to find users
    +
    + Enter a search term to find users +
    {/if}
@@ -454,8 +526,15 @@ class="mb-4" />
- - + +
@@ -469,7 +548,9 @@ class="w-full" />
-
+
{@html preview}
@@ -494,7 +575,7 @@ {#if success} - Comment published successfully to {success.relay}!
+ Comment published successfully to {success.relay}!
Event ID: {success.eventId} +
+ + updateTag(i, (e.target as HTMLInputElement).value, tags[i][1])} + /> + + updateTag(i, tags[i][0], (e.target as HTMLInputElement).value)} + /> +
{/each} -
- +
+
- +
- +
- + {#if dTagError} -
{dTagError}
+
{dTagError}
{/if}
-
- +
+
{#if loading} - Publishing... + Publishing... {/if} {#if error} -
{error}
+
{error}
{/if} {#if success} -
{success}
-
Relays: {publishedRelays.join(', ')}
+
{success}
+
+ Relays: {publishedRelays.join(", ")} +
{#if lastPublishedEventId} -
- Event ID: {lastPublishedEventId} -
{/if} {/if} -
\ No newline at end of file + diff --git a/src/lib/components/EventSearch.svelte b/src/lib/components/EventSearch.svelte index e9dfed2..c32f72b 100644 --- a/src/lib/components/EventSearch.svelte +++ b/src/lib/components/EventSearch.svelte @@ -4,7 +4,11 @@ import { goto } from "$app/navigation"; import type { NDKEvent } from "$lib/utils/nostrUtils"; import RelayDisplay from "./RelayDisplay.svelte"; - import { searchEvent, searchBySubscription, searchNip05 } from "$lib/utils/search_utility"; + import { + searchEvent, + searchBySubscription, + searchNip05, + } from "$lib/utils/search_utility"; import { neventEncode, naddrEncode, nprofileEncode } from "$lib/utils"; import { standardRelays } from "$lib/consts"; import { getMatchingTags, toNpub } from "$lib/utils/nostrUtils"; @@ -33,7 +37,7 @@ eventIds: Set, addresses: Set, searchType?: string, - searchTerm?: string + searchTerm?: string, ) => void; event: NDKEvent | null; onClear?: () => void; @@ -43,7 +47,9 @@ // Component state let searchQuery = $state(""); let localError = $state(null); - let relayStatuses = $state>({}); + let relayStatuses = $state>( + {}, + ); let foundEvent = $state(null); let searching = $state(false); let searchCompleted = $state(false); @@ -56,7 +62,11 @@ let currentAbortController: AbortController | null = null; // Derived values - let hasActiveSearch = $derived(searching || (Object.values(relayStatuses).some(s => s === "pending") && !foundEvent)); + let hasActiveSearch = $derived( + searching || + (Object.values(relayStatuses).some((s) => s === "pending") && + !foundEvent), + ); let showError = $derived(localError || error); let showSuccess = $derived(searchCompleted && searchResultCount !== null); @@ -75,18 +85,39 @@ const foundEvent = await searchNip05(query); if (foundEvent) { handleFoundEvent(foundEvent); - updateSearchState(false, true, 1, 'nip05'); + updateSearchState(false, true, 1, "nip05"); } else { relayStatuses = {}; - if (activeSub) { try { activeSub.stop(); } catch (e) { console.warn('Error stopping subscription:', e); } activeSub = null; } - if (currentAbortController) { currentAbortController.abort(); currentAbortController = null; } - updateSearchState(false, true, 0, 'nip05'); + if (activeSub) { + try { + activeSub.stop(); + } catch (e) { + console.warn("Error stopping subscription:", e); + } + activeSub = null; + } + if (currentAbortController) { + currentAbortController.abort(); + currentAbortController = null; + } + updateSearchState(false, true, 0, "nip05"); } } catch (error) { - localError = error instanceof Error ? error.message : 'NIP-05 lookup failed'; + localError = + error instanceof Error ? error.message : "NIP-05 lookup failed"; relayStatuses = {}; - if (activeSub) { try { activeSub.stop(); } catch (e) { console.warn('Error stopping subscription:', e); } activeSub = null; } - if (currentAbortController) { currentAbortController.abort(); currentAbortController = null; } + if (activeSub) { + try { + activeSub.stop(); + } catch (e) { + console.warn("Error stopping subscription:", e); + } + activeSub = null; + } + if (currentAbortController) { + currentAbortController.abort(); + currentAbortController = null; + } updateSearchState(false, false, null, null); isProcessingSearch = false; currentProcessingSearchValue = null; @@ -102,26 +133,49 @@ console.warn("[Events] Event not found for query:", query); localError = "Event not found"; relayStatuses = {}; - if (activeSub) { try { activeSub.stop(); } catch (e) { console.warn('Error stopping subscription:', e); } activeSub = null; } - if (currentAbortController) { currentAbortController.abort(); currentAbortController = null; } + if (activeSub) { + try { + activeSub.stop(); + } catch (e) { + console.warn("Error stopping subscription:", e); + } + activeSub = null; + } + if (currentAbortController) { + currentAbortController.abort(); + currentAbortController = null; + } updateSearchState(false, false, null, null); } else { console.log("[Events] Event found:", foundEvent); handleFoundEvent(foundEvent); - updateSearchState(false, true, 1, 'event'); + updateSearchState(false, true, 1, "event"); } } catch (err) { console.error("[Events] Error fetching event:", err, "Query:", query); localError = "Error fetching event. Please check the ID and try again."; relayStatuses = {}; - if (activeSub) { try { activeSub.stop(); } catch (e) { console.warn('Error stopping subscription:', e); } activeSub = null; } - if (currentAbortController) { currentAbortController.abort(); currentAbortController = null; } + if (activeSub) { + try { + activeSub.stop(); + } catch (e) { + console.warn("Error stopping subscription:", e); + } + activeSub = null; + } + if (currentAbortController) { + currentAbortController.abort(); + currentAbortController = null; + } updateSearchState(false, false, null, null); isProcessingSearch = false; } } - async function handleSearchEvent(clearInput: boolean = true, queryOverride?: string) { + async function handleSearchEvent( + clearInput: boolean = true, + queryOverride?: string, + ) { if (searching) { console.log("EventSearch: Already searching, skipping"); return; @@ -131,7 +185,9 @@ updateSearchState(true); isResetting = false; isUserEditing = false; // Reset user editing flag when search starts - const query = (queryOverride !== undefined ? queryOverride : searchQuery).trim(); + const query = ( + queryOverride !== undefined ? queryOverride : searchQuery + ).trim(); if (!query) { updateSearchState(false, false, null, null); return; @@ -140,7 +196,7 @@ const dTag = query.slice(2).trim().toLowerCase(); if (dTag) { console.log("EventSearch: Processing d-tag search:", dTag); - navigateToSearch(dTag, 'd'); + navigateToSearch(dTag, "d"); updateSearchState(false, false, null, null); return; } @@ -148,23 +204,23 @@ if (query.toLowerCase().startsWith("t:")) { const searchTerm = query.slice(2).trim(); if (searchTerm) { - await handleSearchBySubscription('t', searchTerm); + await handleSearchBySubscription("t", searchTerm); return; } } if (query.toLowerCase().startsWith("n:")) { const searchTerm = query.slice(2).trim(); if (searchTerm) { - await handleSearchBySubscription('n', searchTerm); + await handleSearchBySubscription("n", searchTerm); return; } } - if (query.includes('@')) { + if (query.includes("@")) { await handleNip05Search(query); return; } if (clearInput) { - navigateToSearch(query, 'id'); + navigateToSearch(query, "id"); // Don't clear searchQuery here - let the effect handle it } await handleEventSearch(query); @@ -176,7 +232,7 @@ if (searching || isResetting || isUserEditing) { return; } - + if (dTagValue) { // If dTagValue is set, show it as "d:tag" in the search bar searchQuery = `d:${dTagValue}`; @@ -191,7 +247,13 @@ // Debounced effect to handle searchValue changes $effect(() => { - if (!searchValue || searching || isResetting || isProcessingSearch || isWaitingForSearchResult) { + if ( + !searchValue || + searching || + isResetting || + isProcessingSearch || + isWaitingForSearchResult + ) { return; } @@ -205,7 +267,7 @@ currentNevent = neventEncode(foundEvent, standardRelays); } catch {} try { - currentNaddr = getMatchingTags(foundEvent, 'd')[0]?.[1] + currentNaddr = getMatchingTags(foundEvent, "d")[0]?.[1] ? naddrEncode(foundEvent, standardRelays) : null; } catch {} @@ -214,11 +276,30 @@ } catch {} // Debug log for comparison - console.log('[EventSearch effect] searchValue:', searchValue, 'foundEvent.id:', currentEventId, 'foundEvent.pubkey:', foundEvent.pubkey, 'toNpub(pubkey):', currentNpub, 'foundEvent.kind:', foundEvent.kind, 'currentNaddr:', currentNaddr, 'currentNevent:', currentNevent); + console.log( + "[EventSearch effect] searchValue:", + searchValue, + "foundEvent.id:", + currentEventId, + "foundEvent.pubkey:", + foundEvent.pubkey, + "toNpub(pubkey):", + currentNpub, + "foundEvent.kind:", + foundEvent.kind, + "currentNaddr:", + currentNaddr, + "currentNevent:", + currentNevent, + ); // Also check if searchValue is an nprofile and matches the current event's pubkey let currentNprofile = null; - if (searchValue && searchValue.startsWith('nprofile1') && foundEvent.kind === 0) { + if ( + searchValue && + searchValue.startsWith("nprofile1") && + foundEvent.kind === 0 + ) { try { currentNprofile = nprofileEncode(foundEvent.pubkey, standardRelays); } catch {} @@ -261,10 +342,15 @@ // Simple effect to handle dTagValue changes $effect(() => { - if (dTagValue && !searching && !isResetting && dTagValue !== lastProcessedDTagValue) { + if ( + dTagValue && + !searching && + !isResetting && + dTagValue !== lastProcessedDTagValue + ) { console.log("EventSearch: Processing dTagValue:", dTagValue); lastProcessedDTagValue = dTagValue; - handleSearchBySubscription('d', dTagValue); + handleSearchBySubscription("d", dTagValue); } }); @@ -276,7 +362,12 @@ }); // Search utility functions - function updateSearchState(isSearching: boolean, completed: boolean = false, count: number | null = null, type: string | null = null) { + function updateSearchState( + isSearching: boolean, + completed: boolean = false, + count: number | null = null, + type: string | null = null, + ) { searching = isSearching; searchCompleted = completed; searchResultCount = count; @@ -297,32 +388,32 @@ currentProcessingSearchValue = null; lastSearchValue = null; updateSearchState(false, false, null, null); - + // Cancel ongoing search if (currentAbortController) { currentAbortController.abort(); currentAbortController = null; } - + // Clean up subscription if (activeSub) { try { activeSub.stop(); } catch (e) { - console.warn('Error stopping subscription:', e); + console.warn("Error stopping subscription:", e); } activeSub = null; } - + // Clear search results onSearchResults([], [], [], new Set(), new Set()); - + // Clear any pending timeout if (searchTimeout) { clearTimeout(searchTimeout); searchTimeout = null; } - + // Reset the flag after a short delay to allow effects to settle setTimeout(() => { isResetting = false; @@ -332,40 +423,40 @@ function handleFoundEvent(event: NDKEvent) { foundEvent = event; relayStatuses = {}; // Clear relay statuses when event is found - + // Stop any ongoing subscription if (activeSub) { try { activeSub.stop(); } catch (e) { - console.warn('Error stopping subscription:', e); + console.warn("Error stopping subscription:", e); } activeSub = null; } - + // Abort any ongoing fetch if (currentAbortController) { currentAbortController.abort(); currentAbortController = null; } - + // Clear search state searching = false; searchCompleted = true; searchResultCount = 1; - searchResultType = 'event'; - + searchResultType = "event"; + // Update last processed search value to prevent re-processing if (searchValue) { lastProcessedSearchValue = searchValue; lastSearchValue = searchValue; } - + // Reset processing flag isProcessingSearch = false; currentProcessingSearchValue = null; isWaitingForSearchResult = false; - + onEventFound(event); } @@ -379,8 +470,14 @@ } // Search handlers - async function handleSearchBySubscription(searchType: 'd' | 't' | 'n', searchTerm: string) { - console.log("EventSearch: Starting subscription search:", { searchType, searchTerm }); + async function handleSearchBySubscription( + searchType: "d" | "t" | "n", + searchTerm: string, + ) { + console.log("EventSearch: Starting subscription search:", { + searchType, + searchTerm, + }); isResetting = false; // Allow effects to run for new searches localError = null; updateSearchState(true); @@ -403,7 +500,7 @@ updatedResult.eventIds, updatedResult.addresses, updatedResult.searchType, - updatedResult.searchTerm + updatedResult.searchTerm, ); }, onSubscriptionCreated: (sub) => { @@ -412,9 +509,9 @@ activeSub.stop(); } activeSub = sub; - } + }, }, - currentAbortController.signal + currentAbortController.signal, ); console.log("EventSearch: Search completed:", result); onSearchResults( @@ -424,16 +521,19 @@ result.eventIds, result.addresses, result.searchType, - result.searchTerm + result.searchTerm, ); - const totalCount = result.events.length + result.secondOrder.length + result.tTagEvents.length; + const totalCount = + result.events.length + + result.secondOrder.length + + result.tTagEvents.length; relayStatuses = {}; // Clear relay statuses when search completes // Stop any ongoing subscription if (activeSub) { try { activeSub.stop(); } catch (e) { - console.warn('Error stopping subscription:', e); + console.warn("Error stopping subscription:", e); } activeSub = null; } @@ -447,20 +547,25 @@ currentProcessingSearchValue = null; isWaitingForSearchResult = false; } catch (error) { - if (error instanceof Error && error.message === 'Search cancelled') { + if (error instanceof Error && error.message === "Search cancelled") { isProcessingSearch = false; currentProcessingSearchValue = null; isWaitingForSearchResult = false; return; } console.error("EventSearch: Search failed:", error); - localError = error instanceof Error ? error.message : 'Search failed'; + localError = error instanceof Error ? error.message : "Search failed"; // Provide more specific error messages for different failure types if (error instanceof Error) { - if (error.message.includes('timeout') || error.message.includes('connection')) { - localError = 'Search timed out. The relays may be temporarily unavailable. Please try again.'; - } else if (error.message.includes('NDK not initialized')) { - localError = 'Nostr client not initialized. Please refresh the page and try again.'; + if ( + error.message.includes("timeout") || + error.message.includes("connection") + ) { + localError = + "Search timed out. The relays may be temporarily unavailable. Please try again."; + } else if (error.message.includes("NDK not initialized")) { + localError = + "Nostr client not initialized. Please refresh the page and try again."; } else { localError = `Search failed: ${error.message}`; } @@ -471,35 +576,35 @@ try { activeSub.stop(); } catch (e) { - console.warn('Error stopping subscription:', e); + console.warn("Error stopping subscription:", e); + } + activeSub = null; } - activeSub = null; - } - // Abort any ongoing fetch - if (currentAbortController) { - currentAbortController.abort(); - currentAbortController = null; + // Abort any ongoing fetch + if (currentAbortController) { + currentAbortController.abort(); + currentAbortController = null; + } + updateSearchState(false, false, null, null); + isProcessingSearch = false; + currentProcessingSearchValue = null; + isWaitingForSearchResult = false; } - updateSearchState(false, false, null, null); - isProcessingSearch = false; - currentProcessingSearchValue = null; - isWaitingForSearchResult = false; - } } function handleClear() { isResetting = true; - searchQuery = ''; + searchQuery = ""; isUserEditing = false; // Reset user editing flag resetSearchState(); - + // Clear URL parameters to reset the page - goto('', { + goto("", { replaceState: true, keepFocus: true, noScroll: true, }); - + // Ensure all search state is cleared searching = false; searchCompleted = false; @@ -512,17 +617,17 @@ currentProcessingSearchValue = null; lastSearchValue = null; isWaitingForSearchResult = false; - + // Clear any pending timeout if (searchTimeout) { clearTimeout(searchTimeout); searchTimeout = null; } - + if (onClear) { onClear(); } - + // Reset the flag after a short delay to allow effects to settle setTimeout(() => { isResetting = false; @@ -533,12 +638,16 @@ if (searchResultCount === 0) { return "Search completed. No results found."; } - - const typeLabel = searchResultType === 'n' ? 'profile' : - searchResultType === 'nip05' ? 'NIP-05 address' : 'event'; - const countLabel = searchResultType === 'n' ? 'profiles' : 'events'; - - return searchResultCount === 1 + + const typeLabel = + searchResultType === "n" + ? "profile" + : searchResultType === "nip05" + ? "NIP-05 address" + : "event"; + const countLabel = searchResultType === "n" ? "profiles" : "events"; + + return searchResultCount === 1 ? `Search completed. Found 1 ${typeLabel}.` : `Search completed. Found ${searchResultCount} ${countLabel}.`; } @@ -551,9 +660,10 @@ bind:value={searchQuery} placeholder="Enter event ID, nevent, naddr, d:tag-name, t:topic, or n:username..." class="flex-grow" - onkeydown={(e: KeyboardEvent) => e.key === "Enter" && handleSearchEvent(true)} - oninput={() => isUserEditing = true} - onblur={() => isUserEditing = false} + onkeydown={(e: KeyboardEvent) => + e.key === "Enter" && handleSearchEvent(true)} + oninput={() => (isUserEditing = true)} + onblur={() => (isUserEditing = false)} /> - {/if} {#if !isLeaf} - {#if publicationType === 'blog'} + {#if publicationType === "blog"} {:else if !$publicationColumnVisibility.discussion && !$publicationColumnVisibility.toc} {/if} - {#if publicationType !== 'blog' && !$publicationColumnVisibility.discussion} - {/if} - \ No newline at end of file + diff --git a/src/lib/components/util/CardActions.svelte b/src/lib/components/util/CardActions.svelte index ef6b45e..28cab68 100644 --- a/src/lib/components/util/CardActions.svelte +++ b/src/lib/components/util/CardActions.svelte @@ -20,20 +20,42 @@ // Subscribe to userStore let user = $state($userStore); - userStore.subscribe(val => user = val); + userStore.subscribe((val) => (user = val)); // Derive metadata from event - let title = $derived(event.tags.find((t: string[]) => t[0] === 'title')?.[1] ?? ''); - let summary = $derived(event.tags.find((t: string[]) => t[0] === 'summary')?.[1] ?? ''); - let image = $derived(event.tags.find((t: string[]) => t[0] === 'image')?.[1] ?? null); - let author = $derived(event.tags.find((t: string[]) => t[0] === 'author')?.[1] ?? ''); - let originalAuthor = $derived(event.tags.find((t: string[]) => t[0] === 'original_author')?.[1] ?? null); - let version = $derived(event.tags.find((t: string[]) => t[0] === 'version')?.[1] ?? ''); - let source = $derived(event.tags.find((t: string[]) => t[0] === 'source')?.[1] ?? null); - let type = $derived(event.tags.find((t: string[]) => t[0] === 'type')?.[1] ?? null); - let language = $derived(event.tags.find((t: string[]) => t[0] === 'language')?.[1] ?? null); - let publisher = $derived(event.tags.find((t: string[]) => t[0] === 'publisher')?.[1] ?? null); - let identifier = $derived(event.tags.find((t: string[]) => t[0] === 'identifier')?.[1] ?? null); + let title = $derived( + event.tags.find((t: string[]) => t[0] === "title")?.[1] ?? "", + ); + let summary = $derived( + event.tags.find((t: string[]) => t[0] === "summary")?.[1] ?? "", + ); + let image = $derived( + event.tags.find((t: string[]) => t[0] === "image")?.[1] ?? null, + ); + let author = $derived( + event.tags.find((t: string[]) => t[0] === "author")?.[1] ?? "", + ); + let originalAuthor = $derived( + event.tags.find((t: string[]) => t[0] === "original_author")?.[1] ?? null, + ); + let version = $derived( + event.tags.find((t: string[]) => t[0] === "version")?.[1] ?? "", + ); + let source = $derived( + event.tags.find((t: string[]) => t[0] === "source")?.[1] ?? null, + ); + let type = $derived( + event.tags.find((t: string[]) => t[0] === "type")?.[1] ?? null, + ); + let language = $derived( + event.tags.find((t: string[]) => t[0] === "language")?.[1] ?? null, + ); + let publisher = $derived( + event.tags.find((t: string[]) => t[0] === "publisher")?.[1] ?? null, + ); + let identifier = $derived( + event.tags.find((t: string[]) => t[0] === "identifier")?.[1] ?? null, + ); // UI state let detailsModalOpen: boolean = $state(false); @@ -48,7 +70,7 @@ (() => { const isUserFeed = user.signedIn && $feedType === FeedType.UserRelays; const relays = isUserFeed ? user.relays.inbox : standardRelays; - + console.debug("[CardActions] Selected relays:", { eventId: event.id, isSignedIn: user.signedIn, @@ -100,7 +122,7 @@ * Navigates to the event details page */ function viewEventDetails() { - const nevent = getIdentifier('nevent'); + const nevent = getIdentifier("nevent"); goto(`/events?id=${encodeURIComponent(nevent)}`); } diff --git a/src/lib/components/util/ContainingIndexes.svelte b/src/lib/components/util/ContainingIndexes.svelte index 1c7da12..992115d 100644 --- a/src/lib/components/util/ContainingIndexes.svelte +++ b/src/lib/components/util/ContainingIndexes.svelte @@ -17,13 +17,19 @@ let lastEventId = $state(null); async function loadContainingIndexes() { - console.log("[ContainingIndexes] Loading containing indexes for event:", event.id); + console.log( + "[ContainingIndexes] Loading containing indexes for event:", + event.id, + ); loading = true; error = null; try { containingIndexes = await findContainingIndexEvents(event); - console.log("[ContainingIndexes] Found containing indexes:", containingIndexes.length); + console.log( + "[ContainingIndexes] Found containing indexes:", + containingIndexes.length, + ); } catch (err) { error = err instanceof Error diff --git a/src/lib/components/util/Details.svelte b/src/lib/components/util/Details.svelte index 9c6d312..ff9643a 100644 --- a/src/lib/components/util/Details.svelte +++ b/src/lib/components/util/Details.svelte @@ -4,37 +4,54 @@ import Interactions from "$components/util/Interactions.svelte"; import { P } from "flowbite-svelte"; import { getMatchingTags } from "$lib/utils/nostrUtils"; - import { goto } from '$app/navigation'; + import { goto } from "$app/navigation"; // isModal // - don't show interactions in modal view // - don't show all the details when _not_ in modal view let { event, isModal = false } = $props(); - let title: string = $derived(getMatchingTags(event, 'title')[0]?.[1]); + let title: string = $derived(getMatchingTags(event, "title")[0]?.[1]); let author: string = $derived( getMatchingTags(event, "author")[0]?.[1] ?? "unknown", ); - let version: string = $derived(getMatchingTags(event, 'version')[0]?.[1] ?? '1'); - let image: string = $derived(getMatchingTags(event, 'image')[0]?.[1] ?? null); - let summary: string = $derived(getMatchingTags(event, 'summary')[0]?.[1] ?? null); - let type: string = $derived(getMatchingTags(event, 'type')[0]?.[1] ?? null); - let language: string = $derived(getMatchingTags(event, 'l')[0]?.[1] ?? null); - let source: string = $derived(getMatchingTags(event, 'source')[0]?.[1] ?? null); - let publisher: string = $derived(getMatchingTags(event, 'published_by')[0]?.[1] ?? null); - let identifier: string = $derived(getMatchingTags(event, 'i')[0]?.[1] ?? null); - let hashtags: string[] = $derived(getMatchingTags(event, 't').map(tag => tag[1])); - let rootId: string = $derived(getMatchingTags(event, 'd')[0]?.[1] ?? null); + let version: string = $derived( + getMatchingTags(event, "version")[0]?.[1] ?? "1", + ); + let image: string = $derived(getMatchingTags(event, "image")[0]?.[1] ?? null); + let summary: string = $derived( + getMatchingTags(event, "summary")[0]?.[1] ?? null, + ); + let type: string = $derived(getMatchingTags(event, "type")[0]?.[1] ?? null); + let language: string = $derived(getMatchingTags(event, "l")[0]?.[1] ?? null); + let source: string = $derived( + getMatchingTags(event, "source")[0]?.[1] ?? null, + ); + let publisher: string = $derived( + getMatchingTags(event, "published_by")[0]?.[1] ?? null, + ); + let identifier: string = $derived( + getMatchingTags(event, "i")[0]?.[1] ?? null, + ); + let hashtags: string[] = $derived( + getMatchingTags(event, "t").map((tag) => tag[1]), + ); + let rootId: string = $derived(getMatchingTags(event, "d")[0]?.[1] ?? null); let kind = $derived(event.kind); - let authorTag: string = $derived(getMatchingTags(event, 'author')[0]?.[1] ?? ''); - let pTag: string = $derived(getMatchingTags(event, 'p')[0]?.[1] ?? ''); + let authorTag: string = $derived( + getMatchingTags(event, "author")[0]?.[1] ?? "", + ); + let pTag: string = $derived(getMatchingTags(event, "p")[0]?.[1] ?? ""); let originalAuthor: string = $derived( getMatchingTags(event, "p")[0]?.[1] ?? null, ); function isValidNostrPubkey(str: string): boolean { - return /^[a-f0-9]{64}$/i.test(str) || (str.startsWith('npub1') && str.length >= 59 && str.length <= 63); + return ( + /^[a-f0-9]{64}$/i.test(str) || + (str.startsWith("npub1") && str.length >= 59 && str.length <= 63) + ); } @@ -42,7 +59,9 @@ {#if !isModal}
-

{@render userBadge(event.pubkey, author)}

+

{@render userBadge(event.pubkey, author)}

{/if} @@ -63,11 +82,11 @@

by {#if authorTag && pTag && isValidNostrPubkey(pTag)} - {authorTag} {@render userBadge(pTag, '')} + {authorTag} {@render userBadge(pTag, "")} {:else if authorTag} {authorTag} {:else if pTag && isValidNostrPubkey(pTag)} - {@render userBadge(pTag, '')} + {@render userBadge(pTag, "")} {:else if originalAuthor !== null} {@render userBadge(originalAuthor, author)} {:else} @@ -111,7 +130,7 @@ {:else} Author: {/if} - {@render userBadge(event.pubkey, '')} + {@render userBadge(event.pubkey, "")}

diff --git a/src/lib/components/util/Profile.svelte b/src/lib/components/util/Profile.svelte index 88ebe4c..7ba8f81 100644 --- a/src/lib/components/util/Profile.svelte +++ b/src/lib/components/util/Profile.svelte @@ -1,11 +1,15 @@ -
-
+
+
- +
diff --git a/src/routes/about/+page.svelte b/src/routes/about/+page.svelte index caabdcb..72b4697 100644 --- a/src/routes/about/+page.svelte +++ b/src/routes/about/+page.svelte @@ -1,7 +1,7 @@