Browse Source

Fix person anchors to remain fixed after dragging

- Person anchors now maintain their fixed position after being dragged
- Exclude person anchors from gravity forces (like tag anchors)
- Update both regular and star force simulations to handle person anchors
- Ensure person anchors are draggable but stay anchored at their new position

This ensures person nodes behave as true anchors in the visualization,
maintaining their position in the graph even after user interaction.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
master
limina1 9 months ago
parent
commit
d69f126fde
  1. 13
      docs/event-types-panel-redesign.org
  2. 40
      src/lib/navigator/EventNetwork/utils/forceSimulation.ts
  3. 4
      src/lib/navigator/EventNetwork/utils/starForceSimulation.ts

13
docs/event-types-panel-redesign.org

@ -90,3 +90,16 @@ const contentEvents = await $ndkInstance.fetchEvents({ @@ -90,3 +90,16 @@ const contentEvents = await $ndkInstance.fetchEvents({
3. **UX**: Smooth, instant toggle without freezing
4. **Maintainability**: Clear separation of concerns
5. **Scalability**: Handles large numbers of nodes efficiently
* Additional Improvements
** Profile Fetching Optimization
- When follow list limit is 0, only fetch profiles from event authors
- Excludes follow list pubkeys from profile fetching when not needed
- Reduces unnecessary network requests
** Person Node Visual Distinction
- Green diamonds (#10B981) for authors of displayed events
- Kind 3 color for people from follow lists
- Visual clarity on social graph relationships
- Legend updates to match graph coloring

40
src/lib/navigator/EventNetwork/utils/forceSimulation.ts

@ -102,8 +102,8 @@ export function applyGlobalLogGravity( @@ -102,8 +102,8 @@ export function applyGlobalLogGravity(
centerY: number,
alpha: number,
) {
// Tag anchors should not be affected by gravity
if (node.isTagAnchor) return;
// Tag anchors and person anchors should not be affected by gravity
if (node.isTagAnchor || node.isPersonAnchor) return;
const dx = (node.x ?? 0) - centerX;
const dy = (node.y ?? 0) - centerY;
@ -130,14 +130,14 @@ export function applyConnectedGravity( @@ -130,14 +130,14 @@ export function applyConnectedGravity(
links: NetworkLink[],
alpha: number,
) {
// Tag anchors should not be affected by connected gravity
if (node.isTagAnchor) return;
// Tag anchors and person anchors should not be affected by connected gravity
if (node.isTagAnchor || node.isPersonAnchor) return;
// Find all nodes connected to this node (excluding tag anchors)
// Find all nodes connected to this node (excluding tag anchors and person anchors)
const connectedNodes = links
.filter(link => link.source.id === node.id || link.target.id === node.id)
.map(link => link.source.id === node.id ? link.target : link.source)
.filter(n => !n.isTagAnchor);
.filter(n => !n.isTagAnchor && !n.isPersonAnchor);
if (connectedNodes.length === 0) return;
@ -175,8 +175,13 @@ export function setupDragHandlers( @@ -175,8 +175,13 @@ export function setupDragHandlers(
return d3
.drag()
.on("start", (event: D3DragEvent<SVGGElement, NetworkNode, NetworkNode>, d: NetworkNode) => {
// Tag anchors should never be draggable
if (d.isTagAnchor) return;
// Tag anchors and person anchors retain their anchor behavior
if (d.isTagAnchor || d.isPersonAnchor) {
// Still allow dragging but maintain anchor status
d.fx = d.x;
d.fy = d.y;
return;
}
// Warm up simulation if it's cooled down
if (!event.active) {
@ -187,24 +192,29 @@ export function setupDragHandlers( @@ -187,24 +192,29 @@ export function setupDragHandlers(
d.fy = d.y;
})
.on("drag", (event: D3DragEvent<SVGGElement, NetworkNode, NetworkNode>, d: NetworkNode) => {
// Tag anchors should never be draggable
if (d.isTagAnchor) return;
// Update position for all nodes including anchors
// Update fixed position to mouse position
d.fx = event.x;
d.fy = event.y;
})
.on("end", (event: D3DragEvent<SVGGElement, NetworkNode, NetworkNode>, d: NetworkNode) => {
// Tag anchors should never be draggable
if (d.isTagAnchor) return;
// Cool down simulation when drag ends
if (!event.active) {
simulation.alphaTarget(0);
}
// Release fixed position
d.fx = null;
d.fy = null;
// Person anchors should remain fixed after dragging
if (d.isPersonAnchor) {
// Keep the new position fixed
d.fx = d.x;
d.fy = d.y;
} else {
// Release fixed position for other nodes
d.fx = null;
d.fy = null;
}
});
}

4
src/lib/navigator/EventNetwork/utils/starForceSimulation.ts

@ -247,8 +247,8 @@ export function createStarDragHandler( @@ -247,8 +247,8 @@ export function createStarDragHandler(
function dragended(event: any, d: NetworkNode) {
if (!event.active) simulation.alphaTarget(0);
// Tag anchors and star centers stay fixed after dragging
if (d.isTagAnchor || d.kind === 30040) {
// Tag anchors, person anchors, and star centers stay fixed after dragging
if (d.isTagAnchor || d.isPersonAnchor || d.kind === 30040) {
d.fx = event.x;
d.fy = event.y;
} else {

Loading…
Cancel
Save