show inbox state (accepted/blocked) below demo

fetches state via xyz.fake.inbox.getState and displays each user's
accepted and blocked lists. helps visitors understand persisted state.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Changed files
+70 -30
src
lib
routes
+9
src/lib/client.js
··· 78 78 ]) 79 79 ); 80 80 } 81 + 82 + const stateRes = await fetch(`${PDS_URL}/xrpc/xyz.fake.inbox.getState`, { 83 + headers: { Authorization: `Bearer ${this.accessToken}` } 84 + }); 85 + if (stateRes.ok) { 86 + const data = await stateRes.json(); 87 + this.accepted = new Set(data.accepted); 88 + this.blocked = new Set(data.blocked); 89 + } 81 90 } 82 91 83 92 async getServiceAuth(audienceDid, lxm) {
+61 -30
src/routes/+page.svelte
··· 9 9 refresh, 10 10 tick, 11 11 getPds, 12 + getPdsByDid, 12 13 initNetwork, 14 + network, 13 15 ready 14 16 } from '$lib/stores.js'; 15 17 ··· 114 116 labeler.addLabel(sender.did, 'spam'); 115 117 log(`added 'spam' to ${senderHandle}`, 'magenta'); 116 118 } 119 + } 120 + 121 + function getShortName(did) { 122 + const p = getPdsByDid(did); 123 + return p ? p.name : did.slice(8, 16) + '...'; 124 + } 125 + 126 + function formatSet(set) { 127 + if (!set || set.size === 0) return 'none'; 128 + return [...set].map(getShortName).join(', '); 117 129 } 118 130 </script> 119 131 ··· 198 210 {/if} 199 211 </div> 200 212 213 + {#if $ready} 214 + {#key $tick} 215 + <div class="state-summary"> 216 + <h3>current state</h3> 217 + <div class="state-grid"> 218 + {#each Object.values(network) as pds} 219 + <span class="name">{pds.name}</span> 220 + <span class="accepted">accepted: {formatSet(pds.accepted)}</span> 221 + <span class="blocked">blocked: {formatSet(pds.blocked)}</span> 222 + {/each} 223 + </div> 224 + </div> 225 + {/key} 226 + {/if} 227 + 201 228 <footer> 202 229 <p> 203 - demonstrating 204 - <a href="https://bsky.app/profile/jacob.gold/post/3mbsbqsc3vc24"> 205 - jacob.gold's proposal 206 - </a> 207 - for PDS-to-PDS messaging 208 - </p> 209 - <p class="detail"> 210 - each PDS has an inbox queue • service auth proves sender identity • 211 - labelers provide reputation signals 212 - </p> 213 - <p class="src"> 214 - <a href="https://tangled.org/zzstoatzz.io/pds-message-poc">src</a> 230 + inspired by <a href="https://bsky.app/profile/jacob.gold/post/3mbsbqsc3vc24">jacob.gold's post</a> 231 + · 232 + <a href="https://tangled.org/zzstoatzz.io/pds-message-poc">source</a> 215 233 </p> 216 234 </footer> 217 235 ··· 374 392 footer { 375 393 max-width: 1000px; 376 394 margin: 2rem auto 0; 377 - padding: 1.5rem 1rem; 395 + padding: 1rem; 378 396 text-align: center; 379 - border-top: 1px solid #1a1a1a; 380 397 } 381 398 footer p { 382 399 font-size: 11px; ··· 384 401 margin: 0; 385 402 } 386 403 footer a { 387 - color: #1b7340; 404 + color: #555; 388 405 } 389 406 footer a:hover { 390 - color: #2a9d5c; 391 - } 392 - footer .detail { 393 - margin-top: 0.5rem; 394 - font-size: 10px; 395 - color: #383838; 396 - } 397 - footer .src { 398 - margin-top: 1rem; 399 - font-size: 10px; 400 - } 401 - footer .src a { 402 - color: #444; 403 - } 404 - footer .src a:hover { 405 407 color: #888; 406 408 } 407 409 ··· 411 413 padding: 1rem; 412 414 color: #444; 413 415 font-size: 12px; 416 + } 417 + 418 + .state-summary { 419 + max-width: 1000px; 420 + margin: 1.5rem auto 0; 421 + padding: 1rem; 422 + background: #0a0a0a; 423 + border: 1px solid #1a1a1a; 424 + } 425 + .state-summary h3 { 426 + font-size: 10px; 427 + color: #444; 428 + margin-bottom: 0.75rem; 429 + text-transform: lowercase; 430 + } 431 + .state-grid { 432 + display: grid; 433 + grid-template-columns: 60px 160px auto; 434 + gap: 0.4rem 0; 435 + font-size: 11px; 436 + } 437 + .state-grid .name { 438 + color: #888; 439 + } 440 + .state-grid .accepted { 441 + color: #2a9d5c; 442 + } 443 + .state-grid .blocked { 444 + color: #a44; 414 445 } 415 446 </style>