diff --git a/src/lib/navigator/EventNetwork/index.svelte b/src/lib/navigator/EventNetwork/index.svelte index 5d06c69..aebb691 100644 --- a/src/lib/navigator/EventNetwork/index.svelte +++ b/src/lib/navigator/EventNetwork/index.svelte @@ -463,6 +463,12 @@ node.vx = savedPos.vx || 0; node.vy = savedPos.vy || 0; restoredCount++; + } else if (!node.x && !node.y && !node.isTagAnchor && !node.isPersonAnchor) { + // Give disconnected nodes (like kind 0) random initial positions + node.x = width / 2 + (Math.random() - 0.5) * width * 0.5; + node.y = height / 2 + (Math.random() - 0.5) * height * 0.5; + node.vx = 0; + node.vy = 0; } }); @@ -496,6 +502,20 @@ } else { // Use regular simulation simulation = createSimulation(nodes, links, NODE_RADIUS, LINK_DISTANCE); + + // Add center force for disconnected nodes (like kind 0) + simulation.force("center", d3.forceCenter(width / 2, height / 2).strength(0.05)); + + // Add radial force to keep disconnected nodes in view + simulation.force("radial", d3.forceRadial(Math.min(width, height) / 3, width / 2, height / 2) + .strength((d: NetworkNode) => { + // Apply radial force only to nodes without links (disconnected nodes) + const hasLinks = links.some(l => + (l.source as NetworkNode).id === d.id || + (l.target as NetworkNode).id === d.id + ); + return hasLinks ? 0 : 0.1; + })); } // Use gentler alpha for updates with restored positions diff --git a/src/lib/stores/visualizationConfig.ts b/src/lib/stores/visualizationConfig.ts index 5d0b59b..4b8a78d 100644 --- a/src/lib/stores/visualizationConfig.ts +++ b/src/lib/stores/visualizationConfig.ts @@ -42,7 +42,7 @@ function createVisualizationConfig() { appendMode: false, // Legacy properties allowedKinds: DEFAULT_EVENT_CONFIGS.map((ec) => ec.kind), - disabledKinds: [30041, 30818], // Kind 0 not disabled so it shows as green when profiles are fetched + disabledKinds: [30041, 30818, 3, 0], // Kind 0 not disabled so it shows as green when profiles are fetched allowFreeEvents: false, maxPublicationIndices: -1, maxEventsPerIndex: -1, diff --git a/src/lib/utils/displayLimits.ts b/src/lib/utils/displayLimits.ts index 95f5d31..050b0a3 100644 --- a/src/lib/utils/displayLimits.ts +++ b/src/lib/utils/displayLimits.ts @@ -11,8 +11,7 @@ import type { VisualizationConfig } from '$lib/stores/visualizationConfig'; */ export function filterByDisplayLimits(events: NDKEvent[], limits: DisplayLimits, config?: VisualizationConfig): NDKEvent[] { const result: NDKEvent[] = []; - let count30040 = 0; - let count30041 = 0; + const kindCounts = new Map(); for (const event of events) { // First check if the event kind is allowed and not disabled @@ -25,34 +24,24 @@ export function filterByDisplayLimits(events: NDKEvent[], limits: DisplayLimits, } } - // Then apply the count limits - if (event.kind === 30040) { - if (limits.max30040 === -1 || count30040 < limits.max30040) { - result.push(event); - count30040++; - } - } else if (event.kind === 30041) { - if (limits.max30041 === -1 || count30041 < limits.max30041) { + const kind = event.kind; + if (kind === undefined) continue; + + // Get the limit for this event kind from the config + const eventConfig = config?.eventConfigs.find(ec => ec.kind === kind); + const limit = eventConfig?.limit; + + // If there's a limit configured for this kind, check it + if (limit !== undefined) { + const currentCount = kindCounts.get(kind) || 0; + if (currentCount < limit) { result.push(event); - count30041++; + kindCounts.set(kind, currentCount + 1); } } else { - // Other allowed event kinds pass through + // No limit configured, add the event result.push(event); } - - // Early exit optimization if both limits are reached - if (limits.max30040 !== -1 && count30040 >= limits.max30040 && - limits.max30041 !== -1 && count30041 >= limits.max30041) { - // Add remaining non-limited events - const remaining = events.slice(events.indexOf(event) + 1); - for (const e of remaining) { - if (e.kind !== 30040 && e.kind !== 30041) { - result.push(e); - } - } - break; - } } return result;