diff --git a/src/lib/components/content/MediaAttachments.svelte b/src/lib/components/content/MediaAttachments.svelte index b6c094f..cbc7a88 100644 --- a/src/lib/components/content/MediaAttachments.svelte +++ b/src/lib/components/content/MediaAttachments.svelte @@ -6,7 +6,7 @@ } let { event }: Props = $props(); - + interface MediaItem { url: string; type: 'image' | 'video' | 'audio' | 'file'; @@ -216,8 +216,8 @@ preload="metadata" class="max-w-full rounded" style="max-height: 500px;" - autoplay={false} - muted={false} + autoplay={false} + muted={false} > Your browser does not support the video tag. @@ -225,13 +225,13 @@ {:else if item.type === 'audio'}
-
diff --git a/src/lib/components/content/ReplyContext.svelte b/src/lib/components/content/ReplyContext.svelte index 3106c1d..4c89b4e 100644 --- a/src/lib/components/content/ReplyContext.svelte +++ b/src/lib/components/content/ReplyContext.svelte @@ -66,7 +66,7 @@ } finally { // Only clear loading state if this is still the current load if (lastLoadAttemptId === eventId) { - loadingParent = false; + loadingParent = false; } } } diff --git a/src/lib/components/layout/Header.svelte b/src/lib/components/layout/Header.svelte index 7cae309..0e0e7fc 100644 --- a/src/lib/components/layout/Header.svelte +++ b/src/lib/components/layout/Header.svelte @@ -110,7 +110,7 @@ nav { min-width: 0; /* Allow flex items to shrink */ } - + /* Responsive navigation links */ .nav-links { font-size: 0.65rem; @@ -129,7 +129,7 @@ @media (min-width: 640px) { .nav-brand { font-size: 1rem; - } + } } /* Ensure navigation items don't overflow */ diff --git a/src/lib/components/layout/ProfileBadge.svelte b/src/lib/components/layout/ProfileBadge.svelte index 764ea28..5d4e945 100644 --- a/src/lib/components/layout/ProfileBadge.svelte +++ b/src/lib/components/layout/ProfileBadge.svelte @@ -59,9 +59,9 @@ const p = await fetchProfile(currentPubkey); // Only update if pubkey hasn't changed during load if (pubkey === currentPubkey) { - if (p) { - profile = p; - } + if (p) { + profile = p; + } lastLoadedPubkey = currentPubkey; } } finally { diff --git a/src/lib/modules/discussions/DiscussionCard.svelte b/src/lib/modules/discussions/DiscussionCard.svelte index e1a8a08..490867a 100644 --- a/src/lib/modules/discussions/DiscussionCard.svelte +++ b/src/lib/modules/discussions/DiscussionCard.svelte @@ -68,7 +68,7 @@ function toggleExpanded() { expanded = !expanded; } - + async function loadStats() { // Prevent duplicate loads for the same event if (loadingStats || lastStatsLoadEventId === thread.id) { @@ -204,7 +204,7 @@
{#if !fullView} - +

@@ -302,15 +302,15 @@ /> {/if} {#if !fullView} - {#if loadingStats} - Loading stats... - {:else} - {commentCount} {commentCount === 1 ? 'comment' : 'comments'} - {#if latestResponseTime} - Last: {getLatestResponseTime()} - {/if} - {#if zapCount > 0} - ⚡ {zapTotal.toLocaleString()} sats ({zapCount}) + {#if loadingStats} + Loading stats... + {:else} + {commentCount} {commentCount === 1 ? 'comment' : 'comments'} + {#if latestResponseTime} + Last: {getLatestResponseTime()} + {/if} + {#if zapCount > 0} + ⚡ {zapTotal.toLocaleString()} sats ({zapCount}) {/if} {/if} {:else} diff --git a/src/lib/modules/discussions/DiscussionVoteButtons.svelte b/src/lib/modules/discussions/DiscussionVoteButtons.svelte index 03ebf6a..edde9ea 100644 --- a/src/lib/modules/discussions/DiscussionVoteButtons.svelte +++ b/src/lib/modules/discussions/DiscussionVoteButtons.svelte @@ -244,7 +244,7 @@ // Cache of checked reaction IDs to avoid repeated deletion checks const checkedReactionIds = new Set(); - + async function filterDeletedReactions(reactions: NostrEvent[]): Promise { if (reactions.length === 0) return reactions; diff --git a/src/lib/modules/feed/FeedPage.svelte b/src/lib/modules/feed/FeedPage.svelte index cb02a1e..a0ef58b 100644 --- a/src/lib/modules/feed/FeedPage.svelte +++ b/src/lib/modules/feed/FeedPage.svelte @@ -32,7 +32,7 @@ let isMounted = $state(true); let initialLoadComplete = $state(false); let loadInProgress = $state(false); - + // Load waiting room events into feed function loadWaitingRoomEvents() { if (waitingRoomEvents.length === 0) return; @@ -67,9 +67,9 @@ filters, relays, { - relayFirst: true, - useCache: true, - cacheResults: true, + relayFirst: true, + useCache: true, + cacheResults: true, timeout: config.standardTimeout } ); @@ -89,7 +89,7 @@ const eventMap = new Map(events.map(e => [e.id, e])); for (const event of filtered) { eventMap.set(event.id, event); - } + } const sorted = Array.from(eventMap.values()).sort((a, b) => b.created_at - a.created_at); events = sorted; @@ -115,10 +115,10 @@ const feedKinds = getFeedKinds().filter(k => k !== KIND.DISCUSSION_THREAD); const cached = await getRecentFeedEvents(feedKinds, 15 * 60 * 1000, config.feedLimit); const filtered = cached.filter(e => - e.kind !== KIND.DISCUSSION_THREAD && - getKindInfo(e.kind).showInFeed === true - ); - + e.kind !== KIND.DISCUSSION_THREAD && + getKindInfo(e.kind).showInFeed === true + ); + if (filtered.length > 0 && isMounted) { const unique = Array.from(new Map(filtered.map(e => [e.id, e])).values()); events = unique.sort((a, b) => b.created_at - a.created_at); @@ -136,9 +136,9 @@ relayError = `Relay ${singleRelay} is unavailable.`; loading = false; return; + } } - } - + const feedKinds = getFeedKinds().filter(k => k !== KIND.DISCUSSION_THREAD); const filters = feedKinds.map(k => ({ kinds: [k], limit: config.feedLimit })); @@ -168,8 +168,8 @@ const eventMap = new Map(events.map(e => [e.id, e])); for (const event of filtered) { eventMap.set(event.id, event); - } - + } + const sorted = Array.from(eventMap.values()).sort((a, b) => b.created_at - a.created_at); events = sorted; @@ -206,7 +206,7 @@ const eventIds = new Set([...events.map(e => e.id), ...waitingRoomEvents.map(e => e.id)]); if (!eventIds.has(event.id)) { waitingRoomEvents = [...waitingRoomEvents, event].sort((a, b) => b.created_at - a.created_at); - } + } }, () => {} ); diff --git a/src/lib/modules/feed/FeedPost.svelte b/src/lib/modules/feed/FeedPost.svelte index a833fb3..24d8c6a 100644 --- a/src/lib/modules/feed/FeedPost.svelte +++ b/src/lib/modules/feed/FeedPost.svelte @@ -27,7 +27,7 @@ } let { post, fullView = false, preloadedReactions, parentEvent: providedParentEvent, quotedEvent: providedQuotedEvent }: Props = $props(); - + // Check if this event is bookmarked (async, so we use state) // Only check if user is logged in let bookmarked = $state(false); @@ -93,7 +93,7 @@ if (isLoggedIn) { isBookmarked(post.id).then(b => { if (!cancelled) { - bookmarked = b; + bookmarked = b; } }); } else { @@ -462,8 +462,8 @@ const urlWithoutProtocol = normalized.replace(/^https?:\/\//i, ''); if (content.includes(normalized.toLowerCase()) || content.includes(urlWithoutProtocol.toLowerCase())) { return true; - } - + } + // Check if URL appears in markdown image syntax ![alt](url) const markdownImageRegex = /!\[.*?\]\((.*?)\)/gi; let match; @@ -471,7 +471,7 @@ const markdownUrl = normalizeUrl(match[1]); if (markdownUrl === normalized) { return true; - } + } } // Check if URL appears in HTML img/video/audio tags @@ -480,7 +480,7 @@ const htmlUrl = normalizeUrl(match[2]); if (htmlUrl === normalized) { return true; - } + } } return false; @@ -493,14 +493,14 @@ } catch { return url; } - } - + } + // Extract media URLs from event tags (image, imeta, file) - for feed view only // Excludes URLs that are already in the content function getMediaUrls(): string[] { const urls: string[] = []; const seen = new Set(); - + // 1. Image tag (NIP-23) const imageTag = post.tags.find((t) => t[0] === 'image'); if (imageTag && imageTag[1]) { @@ -509,7 +509,7 @@ urls.push(imageTag[1]); seen.add(normalized); } - } + } // 2. imeta tags (NIP-92) for (const tag of post.tags) { @@ -536,7 +536,7 @@ if (!seen.has(normalized) && !isUrlInContent(tag[1])) { urls.push(tag[1]); seen.add(normalized); - } + } } } @@ -590,11 +590,11 @@ - {@const title = getTitle()} - {#if title && title !== 'Untitled'} + {@const title = getTitle()} + {#if title && title !== 'Untitled'}

- {title} -

+ {title} +

{/if}
@@ -608,21 +608,21 @@

@@ -636,7 +636,7 @@
- {:else} + {:else}
@@ -651,7 +651,7 @@ {@const topics = getTopics()} {#if topics.length === 0} General - {:else} + {:else} {#each topics.slice(0, 3) as topic} {topic} {/each} @@ -738,22 +738,22 @@ {url} {/each} -
+
{/if} -
- +
+ {#if !fullView && shouldCollapse}
- +
- {/if} - + {/if} + {#if !fullView}
diff --git a/src/lib/modules/feed/ThreadDrawer.svelte b/src/lib/modules/feed/ThreadDrawer.svelte index d368ba2..268015b 100644 --- a/src/lib/modules/feed/ThreadDrawer.svelte +++ b/src/lib/modules/feed/ThreadDrawer.svelte @@ -206,8 +206,8 @@ const eventId = opEvent.id; // Create abort controller to track operation lifecycle - const abortController = new AbortController(); - + const abortController = new AbortController(); + // Load hierarchy with abort signal loadHierarchy(abortController.signal, eventId).catch((error) => { // Handle any unhandled promise rejections @@ -255,7 +255,7 @@ // Load reactions for the single event when drawer opens if (opEvent) { batchLoadReactionsForEvents([opEvent.id]); - } + } } // Don't auto-load hierarchy - only load when "View thread" is clicked @@ -343,7 +343,7 @@ {:else if hierarchyChain.length > 0} - + {#each hierarchyChain as parentEvent, index (parentEvent.id)}
{#if index > 0} @@ -371,7 +371,7 @@ {#if loadFullThread} -
+
-
+
{/if}
{/if} diff --git a/src/lib/modules/profiles/ProfilePage.svelte b/src/lib/modules/profiles/ProfilePage.svelte index 8af0435..91343b1 100644 --- a/src/lib/modules/profiles/ProfilePage.svelte +++ b/src/lib/modules/profiles/ProfilePage.svelte @@ -63,7 +63,7 @@ currentLoadPubkey = null; }; }); - + function openProfileEventsPanel() { profileEventsPanelOpen = true; } @@ -96,7 +96,7 @@ if (currentUserPubkey === pubkey) { // Reload notifications for own profile loadNotifications(pubkey); - } else { + } else { // Reload interactions for other user's profile loadInteractionsWithMe(pubkey, currentUserPubkey); } @@ -535,7 +535,7 @@ activeTab = 'notifications'; } else if (pins.length > 0) { activeTab = 'pins'; - } + } } else { notifications = []; // Load interactions if logged in and viewing another user's profile @@ -552,9 +552,9 @@ } catch (error) { // Only update state if this load wasn't aborted if (!abortController.signal.aborted && currentLoadPubkey === pubkey) { - console.error('Error loading profile:', error); - loading = false; - profile = null; + console.error('Error loading profile:', error); + loading = false; + profile = null; } } finally { // Clear load tracking if this was the current load @@ -663,12 +663,12 @@ Pins ({pins.length}) {#if isOwnProfile} - + {:else if currentUserPubkey && currentUserPubkey !== profilePubkey}