Browse Source

gif picker

get rid of grayscale on images
master
Silberengel 1 month ago
parent
commit
d374ba024b
  1. 15
      src/app.css
  2. 2
      src/lib/components/content/EmojiPicker.svelte
  3. 70
      src/lib/components/content/GifPicker.svelte
  4. 7
      src/lib/components/layout/ProfileBadge.svelte
  5. 5
      src/lib/modules/comments/CommentForm.svelte
  6. 22
      src/lib/modules/reactions/FeedReactionButtons.svelte
  7. 24
      src/lib/services/nostr/gif-service.ts
  8. 11
      src/lib/services/nostr/nip30-emoji.ts
  9. 46
      src/lib/services/nostr/nostr-client.ts

15
src/app.css

@ -92,7 +92,7 @@ body {
background-color: #1e293b; background-color: #1e293b;
} }
/* Anon aesthetic: Pure gray to slightly bluish tints for profile pics */ /* Profile pictures - display in full color */
/* Profile pictures - all instances */ /* Profile pictures - all instances */
img.profile-picture, img.profile-picture,
.profile-badge img, .profile-badge img,
@ -101,18 +101,7 @@ img[alt*="profile" i],
img[alt*="avatar" i], img[alt*="avatar" i],
img[src*="avatar" i], img[src*="avatar" i],
img[src*="profile" i] { img[src*="profile" i] {
filter: grayscale(100%) sepia(10%) hue-rotate(200deg) saturate(30%) !important; /* No grayscale filter - profile pictures should be in full color */
transition: filter 0.3s ease;
}
.dark img.profile-picture,
.dark .profile-badge img,
.dark .profile-picture,
.dark img[alt*="profile" i],
.dark img[alt*="avatar" i],
.dark img[src*="avatar" i],
.dark img[src*="profile" i] {
filter: grayscale(100%) sepia(12%) hue-rotate(200deg) saturate(35%) !important;
} }
/* Emoji images - no grayscale filter, display in full color */ /* Emoji images - no grayscale filter, display in full color */

2
src/lib/components/content/EmojiPicker.svelte

@ -45,7 +45,7 @@
try { try {
await loadAllEmojiPacks(); await loadAllEmojiPacks();
const allEmojis = getAllCustomEmojis(); const allEmojis = getAllCustomEmojis();
console.log(`[EmojiPicker] Loaded ${allEmojis.length} custom emojis`); console.debug(`[EmojiPicker] Loaded ${allEmojis.length} custom emojis`);
customEmojis = allEmojis; customEmojis = allEmojis;
} catch (error) { } catch (error) {
console.error('Error loading custom emojis:', error); console.error('Error loading custom emojis:', error);

70
src/lib/components/content/GifPicker.svelte

@ -15,21 +15,32 @@
let searchQuery = $state(''); let searchQuery = $state('');
let searchInput: HTMLInputElement | null = $state(null); let searchInput: HTMLInputElement | null = $state(null);
let selectedGif: GifMetadata | null = $state(null); let selectedGif: GifMetadata | null = $state(null);
let error: string | null = $state(null);
// Debounce search // Debounce search
let searchTimeout: ReturnType<typeof setTimeout> | null = null; let searchTimeout: ReturnType<typeof setTimeout> | null = null;
async function loadGifs(query?: string) { async function loadGifs(query?: string) {
loading = true; loading = true;
error = null;
try { try {
console.log('[GifPicker] Loading GIFs, query:', query || 'none');
let results: GifMetadata[];
if (query && query.trim()) { if (query && query.trim()) {
gifs = await searchGifs(query.trim(), 50); results = await searchGifs(query.trim(), 50);
} else { } else {
gifs = await fetchGifs(undefined, 50); results = await fetchGifs(undefined, 50);
}
console.log('[GifPicker] Loaded', results.length, 'GIFs');
gifs = results;
if (results.length === 0 && !query) {
error = 'No GIFs found. Try searching for a specific term, or there may be no GIF events on the relays.';
} }
} catch (error) { } catch (error) {
console.error('[GifPicker] Error loading GIFs:', error); console.error('[GifPicker] Error loading GIFs:', error);
const errorMessage = error instanceof Error ? error.message : String(error);
gifs = []; gifs = [];
error = `Failed to load GIFs: ${errorMessage}`;
} finally { } finally {
loading = false; loading = false;
} }
@ -118,12 +129,22 @@
<div class="gif-picker-content"> <div class="gif-picker-content">
{#if loading} {#if loading}
<div class="gif-loading">Loading GIFs...</div> <div class="gif-loading">Loading GIFs...</div>
{:else if error}
<div class="gif-error">
<p>{error}</p>
<button onclick={() => loadGifs(searchQuery)} class="retry-button">
Retry
</button>
</div>
{:else if gifs.length === 0} {:else if gifs.length === 0}
<div class="gif-empty"> <div class="gif-empty">
{#if searchQuery} {#if searchQuery}
No GIFs found for "{searchQuery}" <p>No GIFs found for "{searchQuery}"</p>
<p class="gif-hint">Try a different search term. The relays were queried but returned no matching kind 94 (NIP94) GIF events.</p>
{:else} {:else}
No GIFs available <p>No GIFs available</p>
<p class="gif-hint">The relays were queried successfully, but no kind 94 (NIP94) GIF events were found. This means there are currently no GIFs published as NIP94 file attachments on the connected relays.</p>
<p class="gif-hint">You can try searching for a specific term, or the relays may not have any GIF events available at this time.</p>
{/if} {/if}
</div> </div>
{:else} {:else}
@ -139,6 +160,11 @@
alt="GIF" alt="GIF"
loading="lazy" loading="lazy"
class="gif-thumbnail" class="gif-thumbnail"
onerror={(e) => {
console.warn('[GifPicker] Failed to load image:', gif.url);
const target = e.target as HTMLImageElement;
target.style.display = 'none';
}}
/> />
</button> </button>
{/each} {/each}
@ -297,7 +323,8 @@
} }
.gif-loading, .gif-loading,
.gif-empty { .gif-empty,
.gif-error {
text-align: center; text-align: center;
padding: 2rem; padding: 2rem;
color: var(--fog-text-light, #9ca3af); color: var(--fog-text-light, #9ca3af);
@ -305,9 +332,40 @@
} }
:global(.dark) .gif-loading, :global(.dark) .gif-loading,
:global(.dark) .gif-empty { :global(.dark) .gif-empty,
:global(.dark) .gif-error {
color: var(--fog-dark-text-light, #6b7280); color: var(--fog-dark-text-light, #6b7280);
} }
.gif-hint {
margin-top: 0.5rem;
font-size: 0.75rem;
opacity: 0.8;
}
.gif-error {
color: var(--fog-error, #dc2626);
}
:global(.dark) .gif-error {
color: var(--fog-dark-error, #ef4444);
}
.retry-button {
margin-top: 1rem;
padding: 0.5rem 1rem;
background: var(--fog-accent, #64748b);
color: white;
border: none;
border-radius: 0.375rem;
cursor: pointer;
font-size: 0.875rem;
transition: opacity 0.2s;
}
.retry-button:hover {
opacity: 0.9;
}
.gif-grid { .gif-grid {
display: grid; display: grid;

7
src/lib/components/layout/ProfileBadge.svelte

@ -104,7 +104,7 @@
{:else} {:else}
<div <div
class="profile-placeholder w-6 h-6 rounded flex-shrink-0 flex items-center justify-center text-xs font-semibold" class="profile-placeholder w-6 h-6 rounded flex-shrink-0 flex items-center justify-center text-xs font-semibold"
style="background: {avatarColor}; color: white; filter: grayscale(100%) sepia(10%) hue-rotate(200deg) saturate(30%);" style="background: {avatarColor}; color: white;"
title={pubkey} title={pubkey}
> >
{avatarInitials} {avatarInitials}
@ -122,13 +122,12 @@
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
max-width: 100%; max-width: 100%;
filter: grayscale(100%) opacity(0.7); transition: opacity 0.2s;
transition: filter 0.2s;
} }
.profile-badge:hover { .profile-badge:hover {
text-decoration: underline; text-decoration: underline;
filter: grayscale(100%) opacity(0.9); opacity: 0.9;
} }
.profile-picture { .profile-picture {

5
src/lib/modules/comments/CommentForm.svelte

@ -191,7 +191,10 @@
<div class="textarea-buttons"> <div class="textarea-buttons">
<button <button
type="button" type="button"
onclick={() => { showGifPicker = !showGifPicker; showEmojiPicker = false; }} onclick={() => {
showGifPicker = !showGifPicker;
showEmojiPicker = false;
}}
class="toolbar-button" class="toolbar-button"
title="Insert GIF" title="Insert GIF"
aria-label="Insert GIF" aria-label="Insert GIF"

22
src/lib/modules/reactions/FeedReactionButtons.svelte

@ -71,7 +71,7 @@
// Handle real-time updates - process reactions when new ones arrive // Handle real-time updates - process reactions when new ones arrive
async function handleReactionUpdate(updated: NostrEvent[]) { async function handleReactionUpdate(updated: NostrEvent[]) {
console.log(`[FeedReactionButtons] Received reaction update for event ${event.id.substring(0, 16)}...:`, { console.debug(`[FeedReactionButtons] Received reaction update for event ${event.id.substring(0, 16)}...:`, {
count: updated.length, count: updated.length,
events: updated.map(r => ({ events: updated.map(r => ({
id: r.id.substring(0, 16) + '...', id: r.id.substring(0, 16) + '...',
@ -103,8 +103,8 @@
// Use getProfileReadRelays() to include defaultRelays + profileRelays + user inbox + localRelays // Use getProfileReadRelays() to include defaultRelays + profileRelays + user inbox + localRelays
// This ensures we get all reactions from the complete relay set, matching ThreadList behavior // This ensures we get all reactions from the complete relay set, matching ThreadList behavior
const reactionRelays = relayManager.getProfileReadRelays(); const reactionRelays = relayManager.getProfileReadRelays();
console.log(`[FeedReactionButtons] Loading reactions for event ${event.id.substring(0, 16)}... (kind ${event.kind})`); console.debug(`[FeedReactionButtons] Loading reactions for event ${event.id.substring(0, 16)}... (kind ${event.kind})`);
console.log(`[FeedReactionButtons] Using relays:`, reactionRelays); console.debug(`[FeedReactionButtons] Using relays:`, reactionRelays);
// Clear and rebuild reactions map for this event // Clear and rebuild reactions map for this event
allReactionsMap.clear(); allReactionsMap.clear();
@ -120,7 +120,7 @@
{ useCache: true, cacheResults: true, onUpdate: handleReactionUpdate } { useCache: true, cacheResults: true, onUpdate: handleReactionUpdate }
); );
console.log(`[FeedReactionButtons] Reactions fetched:`, { console.debug(`[FeedReactionButtons] Reactions fetched:`, {
eventId: event.id.substring(0, 16) + '...', eventId: event.id.substring(0, 16) + '...',
kind: event.kind, kind: event.kind,
withLowerE: reactionsWithLowerE.length, withLowerE: reactionsWithLowerE.length,
@ -150,7 +150,7 @@
} }
const reactionEvents = Array.from(allReactionsMap.values()); const reactionEvents = Array.from(allReactionsMap.values());
console.log(`[FeedReactionButtons] All reactions (deduplicated):`, { console.debug(`[FeedReactionButtons] All reactions (deduplicated):`, {
total: reactionEvents.length, total: reactionEvents.length,
events: reactionEvents.map(r => ({ events: reactionEvents.map(r => ({
id: r.id.substring(0, 16) + '...', id: r.id.substring(0, 16) + '...',
@ -164,7 +164,7 @@
// Filter out deleted reactions (kind 5) // Filter out deleted reactions (kind 5)
const filteredReactions = await filterDeletedReactions(reactionEvents); const filteredReactions = await filterDeletedReactions(reactionEvents);
console.log(`[FeedReactionButtons] After filtering deleted reactions:`, { console.debug(`[FeedReactionButtons] After filtering deleted reactions:`, {
before: reactionEvents.length, before: reactionEvents.length,
after: filteredReactions.length, after: filteredReactions.length,
filtered: reactionEvents.length - filteredReactions.length, filtered: reactionEvents.length - filteredReactions.length,
@ -196,7 +196,7 @@
{ useCache: true } { useCache: true }
); );
console.log(`[FeedReactionButtons] Deletion events fetched:`, { console.debug(`[FeedReactionButtons] Deletion events fetched:`, {
count: deletionEvents.length, count: deletionEvents.length,
events: deletionEvents.map(d => ({ events: deletionEvents.map(d => ({
id: d.id.substring(0, 16) + '...', id: d.id.substring(0, 16) + '...',
@ -221,7 +221,7 @@
} }
} }
console.log(`[FeedReactionButtons] Deleted reaction IDs by pubkey:`, console.debug(`[FeedReactionButtons] Deleted reaction IDs by pubkey:`,
Array.from(deletedReactionIdsByPubkey.entries()).map(([pubkey, ids]) => ({ Array.from(deletedReactionIdsByPubkey.entries()).map(([pubkey, ids]) => ({
pubkey: pubkey.substring(0, 16) + '...', pubkey: pubkey.substring(0, 16) + '...',
deletedIds: Array.from(ids).map(id => id.substring(0, 16) + '...') deletedIds: Array.from(ids).map(id => id.substring(0, 16) + '...')
@ -233,7 +233,7 @@
const deletedIds = deletedReactionIdsByPubkey.get(reaction.pubkey); const deletedIds = deletedReactionIdsByPubkey.get(reaction.pubkey);
const isDeleted = deletedIds && deletedIds.has(reaction.id); const isDeleted = deletedIds && deletedIds.has(reaction.id);
if (isDeleted) { if (isDeleted) {
console.log(`[FeedReactionButtons] Filtering out deleted reaction:`, { console.debug(`[FeedReactionButtons] Filtering out deleted reaction:`, {
id: reaction.id.substring(0, 16) + '...', id: reaction.id.substring(0, 16) + '...',
pubkey: reaction.pubkey.substring(0, 16) + '...', pubkey: reaction.pubkey.substring(0, 16) + '...',
content: reaction.content, content: reaction.content,
@ -247,7 +247,7 @@
} }
async function processReactions(reactionEvents: NostrEvent[]) { async function processReactions(reactionEvents: NostrEvent[]) {
console.log(`[FeedReactionButtons] Processing ${reactionEvents.length} reactions for event ${event.id.substring(0, 16)}... (kind ${event.kind})`); console.debug(`[FeedReactionButtons] Processing ${reactionEvents.length} reactions for event ${event.id.substring(0, 16)}... (kind ${event.kind})`);
const reactionMap = new Map<string, { content: string; pubkeys: Set<string>; eventIds: Map<string, string> }>(); const reactionMap = new Map<string, { content: string; pubkeys: Set<string>; eventIds: Map<string, string> }>();
const currentUser = sessionManager.getCurrentPubkey(); const currentUser = sessionManager.getCurrentPubkey();
let skippedInvalid = 0; let skippedInvalid = 0;
@ -287,7 +287,7 @@
} }
} }
console.log(`[FeedReactionButtons] Processed reactions summary:`, { console.debug(`[FeedReactionButtons] Processed reactions summary:`, {
totalReactions: reactionEvents.length, totalReactions: reactionEvents.length,
skippedInvalid, skippedInvalid,
reactionCounts: Array.from(reactionMap.entries()).map(([content, data]) => ({ reactionCounts: Array.from(reactionMap.entries()).map(([content, data]) => ({

24
src/lib/services/nostr/gif-service.ts

@ -106,6 +106,7 @@ export async function fetchGifs(searchQuery?: string, limit: number = 50): Promi
try { try {
// Use profile read relays to get GIFs // Use profile read relays to get GIFs
const relays = relayManager.getProfileReadRelays(); const relays = relayManager.getProfileReadRelays();
console.debug(`[gif-service] Fetching GIFs from ${relays.length} relays:`, relays);
// Fetch kind 94 events (NIP94 file attachments) // Fetch kind 94 events (NIP94 file attachments)
const filters = [{ const filters = [{
@ -113,18 +114,23 @@ export async function fetchGifs(searchQuery?: string, limit: number = 50): Promi
limit: limit * 2 // Fetch more to filter for GIFs limit: limit * 2 // Fetch more to filter for GIFs
}]; }];
console.debug(`[gif-service] Fetching kind 94 events with filters:`, filters);
const events = await nostrClient.fetchEvents(filters, relays, { const events = await nostrClient.fetchEvents(filters, relays, {
useCache: true, useCache: true,
cacheResults: true cacheResults: true
}); });
console.debug(`[gif-service] Received ${events.length} kind 94 events`);
// Parse and filter for GIFs // Parse and filter for GIFs
const gifs: GifMetadata[] = []; const gifs: GifMetadata[] = [];
console.log(`[gif-service] Processing ${events.length} kind 94 events`); let parsedCount = 0;
let skippedCount = 0;
for (const event of events) { for (const event of events) {
const gif = parseNip94Event(event); const gif = parseNip94Event(event);
if (gif) { if (gif) {
parsedCount++;
// If search query provided, filter by content or tags // If search query provided, filter by content or tags
if (searchQuery) { if (searchQuery) {
const query = searchQuery.toLowerCase(); const query = searchQuery.toLowerCase();
@ -133,21 +139,33 @@ export async function fetchGifs(searchQuery?: string, limit: number = 50): Promi
if (content.includes(query) || tags.includes(query)) { if (content.includes(query) || tags.includes(query)) {
gifs.push(gif); gifs.push(gif);
} else {
skippedCount++;
} }
} else { } else {
gifs.push(gif); gifs.push(gif);
} }
} else {
skippedCount++;
} }
} }
console.log(`[gif-service] Found ${gifs.length} GIFs from ${events.length} events`); console.debug(`[gif-service] Parsed ${parsedCount} GIFs, skipped ${skippedCount} non-GIF events`);
// Only log final result if GIFs were found, otherwise it's just noise
if (gifs.length > 0) {
console.log(`[gif-service] Found ${gifs.length} GIFs${searchQuery ? ` matching "${searchQuery}"` : ''}`);
} else {
console.debug(`[gif-service] Final result: 0 GIFs${searchQuery ? ` matching "${searchQuery}"` : ''}`);
}
// Sort by creation date (newest first) and limit // Sort by creation date (newest first) and limit
gifs.sort((a, b) => b.createdAt - a.createdAt); gifs.sort((a, b) => b.createdAt - a.createdAt);
return gifs.slice(0, limit); return gifs.slice(0, limit);
} catch (error) { } catch (error) {
console.error('[gif-service] Error fetching GIFs:', error); console.error('[gif-service] Error fetching GIFs:', error);
return []; const errorMessage = error instanceof Error ? error.message : String(error);
console.error('[gif-service] Error details:', errorMessage);
throw error; // Re-throw so the UI can show the error
} }
} }

11
src/lib/services/nostr/nip30-emoji.ts

@ -155,7 +155,7 @@ export async function loadAllEmojiPacks(): Promise<void> {
try { try {
// Use profile relays to get emoji packs from more sources // Use profile relays to get emoji packs from more sources
const relays = relayManager.getProfileReadRelays(); const relays = relayManager.getProfileReadRelays();
console.log('[nip30-emoji] Loading all emoji packs/sets...'); console.debug('[nip30-emoji] Loading all emoji packs/sets...');
// Fetch all emoji sets (10030) and emoji packs (30030) // Fetch all emoji sets (10030) and emoji packs (30030)
// Use a high limit to get all available packs - increase limit to get more // Use a high limit to get all available packs - increase limit to get more
@ -165,7 +165,7 @@ export async function loadAllEmojiPacks(): Promise<void> {
{ useCache: true, cacheResults: true, timeout: 15000 } { useCache: true, cacheResults: true, timeout: 15000 }
); );
console.log(`[nip30-emoji] Found ${events.length} emoji pack/set events`); console.debug(`[nip30-emoji] Found ${events.length} emoji pack/set events`);
// Process and cache all emoji sets/packs // Process and cache all emoji sets/packs
// Track shortcode -> (url, created_at) to prefer most recent // Track shortcode -> (url, created_at) to prefer most recent
@ -206,7 +206,12 @@ export async function loadAllEmojiPacks(): Promise<void> {
shortcodeCache.set(shortcode, url); shortcodeCache.set(shortcode, url);
} }
console.log(`[nip30-emoji] Cached ${emojiSetsByPubkey.size} emoji sets with ${shortcodeCache.size} unique shortcodes`); // Only log if we actually found emojis, otherwise it's just noise
if (shortcodeCache.size > 0) {
console.log(`[nip30-emoji] Cached ${emojiSetsByPubkey.size} emoji sets with ${shortcodeCache.size} unique shortcodes`);
} else {
console.debug(`[nip30-emoji] Cached ${emojiSetsByPubkey.size} emoji sets with ${shortcodeCache.size} unique shortcodes`);
}
allEmojiPacksLoaded = true; allEmojiPacksLoaded = true;
} catch (error) { } catch (error) {
console.error('Error loading all emoji packs:', error); console.error('Error loading all emoji packs:', error);

46
src/lib/services/nostr/nostr-client.ts

@ -88,7 +88,8 @@ class NostrClient {
this.relays.set(url, relay); this.relays.set(url, relay);
// Clear failure tracking on successful connection // Clear failure tracking on successful connection
this.failedRelays.delete(url); this.failedRelays.delete(url);
console.log(`[nostr-client] Successfully connected to relay: ${url}`); // Log successful connection at debug level to reduce console noise
console.debug(`[nostr-client] Successfully connected to relay: ${url}`);
} catch (error) { } catch (error) {
// Track the failure // Track the failure
const existingFailure = this.failedRelays.get(url) || { lastFailure: 0, retryAfter: this.INITIAL_RETRY_DELAY, failureCount: 0 }; const existingFailure = this.failedRelays.get(url) || { lastFailure: 0, retryAfter: this.INITIAL_RETRY_DELAY, failureCount: 0 };
@ -156,8 +157,19 @@ class NostrClient {
try { try {
let candidateEvents: NostrEvent[] = []; let candidateEvents: NostrEvent[] = [];
// Query by kind(s) if specified // Prioritize ID queries when IDs are specified (more efficient than querying by kind)
if (filter.kinds && filter.kinds.length > 0) { if (filter.ids && filter.ids.length > 0 && filter.ids.length <= 10) {
// For small number of IDs, query directly by ID
const idEvents: NostrEvent[] = [];
for (const id of filter.ids) {
const event = await getEvent(id);
if (event) {
idEvents.push(event);
}
}
candidateEvents = idEvents;
} else if (filter.kinds && filter.kinds.length > 0) {
// Query by kind(s) if specified
// If single kind, use index for efficiency // If single kind, use index for efficiency
if (filter.kinds.length === 1) { if (filter.kinds.length === 1) {
candidateEvents = await getEventsByKind(filter.kinds[0], (filter.limit || 100) * 3); candidateEvents = await getEventsByKind(filter.kinds[0], (filter.limit || 100) * 3);
@ -210,9 +222,10 @@ class NostrClient {
} }
} }
console.log(`[nostr-client] Cache query found ${candidateEvents.length} candidate events for filter:`, filter);
// Filter candidates by all filter criteria // Filter candidates by all filter criteria
const queriedByIds = filter.ids && filter.ids.length > 0 && filter.ids.length <= 10;
let beforeFilter = candidateEvents.length;
for (const event of candidateEvents) { for (const event of candidateEvents) {
if (seen.has(event.id)) continue; if (seen.has(event.id)) continue;
@ -220,8 +233,8 @@ class NostrClient {
if (filter.since && event.created_at < filter.since) continue; if (filter.since && event.created_at < filter.since) continue;
if (filter.until && event.created_at > filter.until) continue; if (filter.until && event.created_at > filter.until) continue;
// Apply ids filter // Apply ids filter (skip if we already queried by IDs)
if (filter.ids && filter.ids.length > 0 && !filter.ids.includes(event.id)) continue; if (!queriedByIds && filter.ids && filter.ids.length > 0 && !filter.ids.includes(event.id)) continue;
// Apply authors filter (if not already used for query) // Apply authors filter (if not already used for query)
if (filter.authors && filter.authors.length > 0 && !filter.authors.includes(event.pubkey)) continue; if (filter.authors && filter.authors.length > 0 && !filter.authors.includes(event.pubkey)) continue;
@ -279,7 +292,10 @@ class NostrClient {
const limited = sorted.slice(0, limit); const limited = sorted.slice(0, limit);
const filtered = filterEvents(limited); const filtered = filterEvents(limited);
console.log(`[nostr-client] Cache query: ${limited.length} events before filter, ${filtered.length} after filter`); // Only log cache queries that return results to reduce console noise
if (filtered.length > 0) {
console.log(`[nostr-client] Cache query: ${limited.length} events before filter, ${filtered.length} after filter`);
}
return filtered; return filtered;
} catch (error) { } catch (error) {
@ -567,7 +583,7 @@ class NostrClient {
try { try {
const cachedEvents = await this.getCachedEvents(filters); const cachedEvents = await this.getCachedEvents(filters);
if (cachedEvents.length > 0) { if (cachedEvents.length > 0) {
console.log(`[nostr-client] Returning ${cachedEvents.length} cached events for filter:`, filters); console.debug(`[nostr-client] Returning ${cachedEvents.length} cached events for filter:`, filters);
// Return cached immediately, fetch fresh in background with delay // Return cached immediately, fetch fresh in background with delay
// Don't pass onUpdate to background fetch to avoid interfering with cached results // Don't pass onUpdate to background fetch to avoid interfering with cached results
if (cacheResults) { if (cacheResults) {
@ -594,7 +610,8 @@ class NostrClient {
} }
return cachedEvents; return cachedEvents;
} else { } else {
console.log(`[nostr-client] No cached events found for filter:`, filters); // No cached events - this is expected and normal, so use debug level
console.debug(`[nostr-client] No cached events found for filter:`, filters);
} }
} catch (error) { } catch (error) {
console.error('[nostr-client] Error querying cache:', error); console.error('[nostr-client] Error querying cache:', error);
@ -653,7 +670,7 @@ class NostrClient {
return []; return [];
} }
console.log(`[nostr-client] Fetching from ${connectedRelays.length} connected relay(s) out of ${relays.length} requested`); console.debug(`[nostr-client] Fetching from ${connectedRelays.length} connected relay(s) out of ${relays.length} requested`);
// Process relays sequentially with throttling to avoid overload // Process relays sequentially with throttling to avoid overload
const events: Map<string, NostrEvent> = new Map(); const events: Map<string, NostrEvent> = new Map();
@ -680,9 +697,12 @@ class NostrClient {
console.log(`[nostr-client] Fetch returned ${filtered.length} events, calling onUpdate`); console.log(`[nostr-client] Fetch returned ${filtered.length} events, calling onUpdate`);
options.onUpdate(filtered); options.onUpdate(filtered);
} else if (options.onUpdate && filtered.length === 0) { } else if (options.onUpdate && filtered.length === 0) {
console.log(`[nostr-client] Fetch returned 0 events, skipping onUpdate to preserve cached results`); console.debug(`[nostr-client] Fetch returned 0 events, skipping onUpdate to preserve cached results`);
} else if (!options.onUpdate) { } else if (!options.onUpdate) {
console.log(`[nostr-client] Fetch returned ${filtered.length} events (background refresh, no onUpdate)`); // Only log background refreshes that return events, not empty results
if (filtered.length > 0) {
console.debug(`[nostr-client] Fetch returned ${filtered.length} events (background refresh, no onUpdate)`);
}
} }
return filtered; return filtered;

Loading…
Cancel
Save