tangled vouch map with historical data
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: make the lines a bit more pleasant

+45 -11
+45 -11
web/main.js
··· 24 24 let nodeInDenounce = {}; 25 25 let nodeOutVouch = {}; 26 26 let nodeOutDenounce = {}; 27 + let nodeInFollow = {}; 28 + let nodeOutFollow = {}; 27 29 let nodeColors = {}; 28 30 29 31 const edgeFilters = { ··· 127 129 nodeInDenounce = {}; 128 130 nodeOutVouch = {}; 129 131 nodeOutDenounce = {}; 130 - for (const n of nodes) { nodeDegrees[n.id] = 0; nodeInVouch[n.id] = 0; nodeInDenounce[n.id] = 0; nodeOutVouch[n.id] = 0; nodeOutDenounce[n.id] = 0; } 132 + nodeInFollow = {}; 133 + nodeOutFollow = {}; 134 + for (const n of nodes) { nodeDegrees[n.id] = 0; nodeInVouch[n.id] = 0; nodeInDenounce[n.id] = 0; nodeOutVouch[n.id] = 0; nodeOutDenounce[n.id] = 0; nodeInFollow[n.id] = 0; nodeOutFollow[n.id] = 0; } 131 135 for (const link of links) { 132 136 nodeDegrees[link.source] = (nodeDegrees[link.source] || 0) + 1; 133 137 nodeDegrees[link.target] = (nodeDegrees[link.target] || 0) + 1; 134 - if (link.kind === 'vouch/vouch') { nodeInVouch[link.target]++; nodeOutVouch[link.source]++; } 135 - else if (link.kind === 'vouch/denounce') { nodeInDenounce[link.target]++; nodeOutDenounce[link.source]++; } 136 - else if (link.kind === 'vouch/mixed') { nodeInVouch[link.target]++; nodeInDenounce[link.target]++; nodeOutVouch[link.source]++; nodeOutDenounce[link.source]++; } 138 + if (link.kind === 'vouch/vouch') { 139 + nodeOutVouch[link.source]++; 140 + nodeInVouch[link.target]++; 141 + if (link.mutual) { nodeInVouch[link.source]++; nodeOutVouch[link.target]++; } 142 + } 143 + else if (link.kind === 'vouch/denounce') { 144 + nodeOutDenounce[link.source]++; 145 + nodeInDenounce[link.target]++; 146 + if (link.mutual) { nodeInDenounce[link.source]++; nodeOutDenounce[link.target]++; } 147 + } 148 + else if (link.kind === 'vouch/mixed') { 149 + nodeOutVouch[link.source]++; 150 + nodeInVouch[link.target]++; 151 + nodeOutDenounce[link.source]++; 152 + nodeInDenounce[link.target]++; 153 + if (link.mutual) { nodeInVouch[link.source]++; nodeOutVouch[link.target]++; nodeInDenounce[link.source]++; nodeOutDenounce[link.target]++; } 154 + } 155 + else if (link.kind === 'follow') { 156 + nodeOutFollow[link.source]++; 157 + nodeInFollow[link.target]++; 158 + } 137 159 } 138 160 139 161 // pre-compute node colors ··· 166 188 function edgeWidth(kind, mutual) { 167 189 const base = (() => { 168 190 switch (kind) { 169 - case 'vouch/vouch': return 0.8; 170 - case 'vouch/denounce': return 0.6; 171 - case 'vouch/mixed': return 0.8; 172 - case 'follow': return 0.4; 191 + case 'vouch/vouch': return 1; 192 + case 'vouch/denounce': return 1; 193 + case 'vouch/mixed': return 1; 194 + case 'follow': return 1; 173 195 default: return 0.4; 174 196 } 175 197 })(); 176 - return mutual ? base + 0.2 : base; 198 + return mutual ? base + 1 : base; 177 199 } 178 200 179 201 async function loadData() { ··· 225 247 points: { 226 248 pointIdBy: 'id', 227 249 pointColorBy: 'color', 250 + pointColorStrategy: 'direct', 228 251 pointSizeBy: 'size', 229 252 pointSizeStrategy: 'direct', 230 253 pointLabelBy: 'label', ··· 274 297 focusPointOnClick: true, 275 298 selectPointOnClick: 'single', 276 299 pointDefaultColor: isDark ? '#6e738d' : '#9ca0b0', 300 + pointColorStrategy: 'direct', 277 301 pointSizeRange: [5, 20], 278 302 linkDefaultColor: isDark ? 'rgba(107,114,128,0.2)' : 'rgba(107,114,128,0.2)', 279 - linkDefaultWidth: 0.5, 303 + linkDefaultWidth: 1, 280 304 linkWidthStrategy: 'direct', 281 - linkWidthRange: [0.4, 0.8], 305 + linkWidthRange: [1, 2], 282 306 enableSimulation: true, 283 307 onPointMouseOver: (pointIndex) => { 284 308 const id = currentRawPoints[pointIndex]?.id; ··· 332 356 const inD = nodeInDenounce[did] || 0; 333 357 const outV = nodeOutVouch[did] || 0; 334 358 const outD = nodeOutDenounce[did] || 0; 359 + const inF = nodeInFollow[did] || 0; 360 + const outF = nodeOutFollow[did] || 0; 335 361 const total = inV + inD; 336 362 let trustLine = ''; 337 363 if (total > 0 || outV + outD > 0) { ··· 348 374 const sep = inPart && outPart ? ' · ' : ''; 349 375 trustLine = `<div style="margin-top:4px;font-size:0.6875rem">${pctStr} trusted · ${inPart}${sep}${outPart}</div>`; 350 376 } 377 + let followLine = ''; 378 + if (inF > 0 || outF > 0) { 379 + const inPart = inF > 0 ? `<span class="kf">${inF}f</span> in` : ''; 380 + const outPart = outF > 0 ? `<span class="kf">${outF}f</span> out` : ''; 381 + const sep = inPart && outPart ? ' · ' : ''; 382 + followLine = `<div style="font-size:0.6875rem">${inPart}${sep}${outPart}</div>`; 383 + } 351 384 352 385 tooltip.innerHTML = ` 353 386 <div class="tooltip-profile"> ··· 356 389 <div class="tooltip-name">${handle || shortenDID(did)}</div> 357 390 ${handle ? `<div class="tooltip-handle">${shortenDID(did)}</div>` : ''} 358 391 ${trustLine} 392 + ${followLine} 359 393 </div> 360 394 </div> 361 395 `;