diff --git a/src/lib/navigator/EventNetwork/Legend.svelte b/src/lib/navigator/EventNetwork/Legend.svelte index 909cad8..63b9aaa 100644 --- a/src/lib/navigator/EventNetwork/Legend.svelte +++ b/src/lib/navigator/EventNetwork/Legend.svelte @@ -386,7 +386,7 @@
diff --git a/src/lib/navigator/EventNetwork/index.svelte b/src/lib/navigator/EventNetwork/index.svelte index 8c91334..5d06c69 100644 --- a/src/lib/navigator/EventNetwork/index.svelte +++ b/src/lib/navigator/EventNetwork/index.svelte @@ -336,8 +336,8 @@ if (showPersonNodes) { debug("Creating person anchor nodes"); - // Extract unique persons from events - personMap = extractUniquePersons(events); + // Extract unique persons from events and follow lists + personMap = extractUniquePersons(events, followListEvents); // Create person anchor nodes based on filters const personResult = createPersonAnchorNodes( @@ -639,8 +639,13 @@ return baseClasses; }) .style("fill", (d: NetworkNode) => { - // Person anchors are green + // Person anchors - color based on source if (d.isPersonAnchor) { + // If from follow list, use kind 3 color + if (d.isFromFollowList) { + return getEventKindColor(3); + } + // Otherwise green for event authors return "#10B981"; } // Tag anchors get their specific colors @@ -870,8 +875,17 @@ if (svgGroup) { svgGroup .selectAll("g.node") - .select("circle.visual-circle") + .select(".visual-shape") .style("fill", (d: NetworkNode) => { + // Person anchors - color based on source + if (d.isPersonAnchor) { + // If from follow list, use kind 3 color + if (d.isFromFollowList) { + return getEventKindColor(3); + } + // Otherwise green for event authors + return "#10B981"; + } if (d.isTagAnchor) { return getTagAnchorColor(d.tagType || ""); } diff --git a/src/lib/navigator/EventNetwork/types.ts b/src/lib/navigator/EventNetwork/types.ts index d0d579c..67fe49f 100644 --- a/src/lib/navigator/EventNetwork/types.ts +++ b/src/lib/navigator/EventNetwork/types.ts @@ -58,6 +58,7 @@ export interface NetworkNode extends SimulationNodeDatum { isPersonAnchor?: boolean; // Whether this is a person anchor node pubkey?: string; // The person's public key displayName?: string; // The person's display name from kind 0 + isFromFollowList?: boolean; // Whether this person comes from follow lists } /** diff --git a/src/lib/navigator/EventNetwork/utils/personNetworkBuilder.ts b/src/lib/navigator/EventNetwork/utils/personNetworkBuilder.ts index 38f7ed7..5d9bfb9 100644 --- a/src/lib/navigator/EventNetwork/utils/personNetworkBuilder.ts +++ b/src/lib/navigator/EventNetwork/utils/personNetworkBuilder.ts @@ -44,6 +44,7 @@ function createSeed(str: string): number { export interface PersonConnection { signedByEventIds: Set; referencedInEventIds: Set; + isFromFollowList?: boolean; // Track if this person comes from follow lists } /** @@ -51,12 +52,33 @@ export interface PersonConnection { * Tracks both signed-by (event.pubkey) and referenced (["p", pubkey] tags) */ export function extractUniquePersons( - events: NDKEvent[] + events: NDKEvent[], + followListEvents?: NDKEvent[] ): Map { // Map of pubkey -> PersonConnection const personMap = new Map(); console.log(`[PersonBuilder] Extracting persons from ${events.length} events`); + + // First collect pubkeys from follow list events + const followListPubkeys = new Set(); + if (followListEvents && followListEvents.length > 0) { + console.log(`[PersonBuilder] Processing ${followListEvents.length} follow list events`); + followListEvents.forEach((event) => { + // Follow list author + if (event.pubkey) { + followListPubkeys.add(event.pubkey); + } + // People in follow lists (p tags) + if (event.tags) { + event.tags.forEach(tag => { + if (tag[0] === "p" && tag[1]) { + followListPubkeys.add(tag[1]); + } + }); + } + }); + } events.forEach((event) => { if (!event.id) return; @@ -66,7 +88,8 @@ export function extractUniquePersons( if (!personMap.has(event.pubkey)) { personMap.set(event.pubkey, { signedByEventIds: new Set(), - referencedInEventIds: new Set() + referencedInEventIds: new Set(), + isFromFollowList: followListPubkeys.has(event.pubkey) }); } personMap.get(event.pubkey)!.signedByEventIds.add(event.id); @@ -80,7 +103,8 @@ export function extractUniquePersons( if (!personMap.has(referencedPubkey)) { personMap.set(referencedPubkey, { signedByEventIds: new Set(), - referencedInEventIds: new Set() + referencedInEventIds: new Set(), + isFromFollowList: followListPubkeys.has(referencedPubkey) }); } personMap.get(referencedPubkey)!.referencedInEventIds.add(event.id); @@ -90,6 +114,7 @@ export function extractUniquePersons( }); console.log(`[PersonBuilder] Found ${personMap.size} unique persons`); + console.log(`[PersonBuilder] ${followListPubkeys.size} are from follow lists`); return personMap; } @@ -172,6 +197,7 @@ export function createPersonAnchorNodes( pubkey, displayName, connectedNodes: Array.from(connectedEventIds), + isFromFollowList: connection.isFromFollowList, x, y, fx: x, // Fix position @@ -241,6 +267,7 @@ export interface PersonAnchorInfo { displayName: string; signedByCount: number; referencedCount: number; + isFromFollowList: boolean; } /** @@ -257,6 +284,7 @@ export function extractPersonAnchorInfo( displayName: anchor.displayName || "", signedByCount: connection?.signedByEventIds.size || 0, referencedCount: connection?.referencedInEventIds.size || 0, + isFromFollowList: connection?.isFromFollowList || false, }; }); } \ No newline at end of file diff --git a/src/routes/visualize/+page.svelte b/src/routes/visualize/+page.svelte index ee941f7..62885d0 100644 --- a/src/routes/visualize/+page.svelte +++ b/src/routes/visualize/+page.svelte @@ -509,8 +509,13 @@ // Use the utility function to extract ALL pubkeys (authors + p tags + content) const allPubkeys = extractPubkeysFromEvents(allEvents); - // Add pubkeys from follow lists if present - if (followListEvents.length > 0) { + // Check if follow list is configured with limit > 0 + const followListConfig = allConfigs.find(c => c.kind === 3); + const shouldIncludeFollowPubkeys = followListConfig && followListConfig.limit > 0; + + // Add pubkeys from follow lists only if follow list limit > 0 + if (shouldIncludeFollowPubkeys && followListEvents.length > 0) { + debug("Including pubkeys from follow lists (limit > 0)"); followListEvents.forEach(event => { if (event.pubkey) allPubkeys.add(event.pubkey); event.tags.forEach(tag => { @@ -519,6 +524,8 @@ } }); }); + } else if (!shouldIncludeFollowPubkeys && followListEvents.length > 0) { + debug("Excluding follow list pubkeys (limit = 0, only fetching event authors)"); } debug("Profile extraction complete:", {