browse the protocol like its 2008 ibex.desertthunder.dev
ubuntu atproto svelte
7

Configure Feed

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

feat: expand About Computer

Owais Jamil (Jun 19, 2026, 1:38 PM -0500) 5410e01e f3e5e89d

+199 -43
+2 -2
TODO.md
··· 64 64 streams. 65 65 - Filter by DID, collection, cursor, and stream instance where supported. 66 66 - Show event rate, total events, top collections/sources, expandable JSON, and copy. 67 - - [ ] **Identity Inspector** 67 + - [x] **Identity Inspector** 68 68 - Icon: `/icons/humanity/apps/identity-inspector.svg`. 69 69 - Show DID document, aliases, services, verification methods, and rotation keys. 70 70 - Validate handles through DNS TXT and `.well-known` when possible. ··· 103 103 - Keep lookup public/read-only. 104 104 - Make unsupported NSIDs clear: ATProto does not define universal automated NSID 105 105 schema fetching or enumeration. 106 - - [ ] **About This Computer** 106 + - [x] **About This Computer** 107 107 - Show OS/theme info and current public repo identity metadata when available. 108 108 109 109 ## Priority Order
+197 -41
src/lib/components/AboutComputer.svelte
··· 1 1 <script lang="ts"> 2 + import { repoSession } from '$lib/atproto/session.svelte'; 2 3 import { accountSetup } from '$lib/atproto/setup.svelte'; 3 4 import { buildCommitUrl, buildVersion } from '$lib/version'; 4 5 import { REPO_URL } from '$lib/constants'; 6 + 7 + const identity = $derived(repoSession.identity ?? accountSetup.identity); 8 + const identitySource = $derived(repoSession.identity ? 'Current public repository' : 'Default public repository'); 9 + const profileName = $derived(identity?.displayName ?? (identity ? `@${identity.handle}` : 'No repository')); 10 + const repositorySource = $derived(identity ? identitySource : 'Unavailable'); 11 + const repositoryHandle = $derived(identity ? `@${identity.handle}` : '—'); 5 12 </script> 6 13 7 14 <section class="about-computer" aria-labelledby="about-title"> ··· 14 21 </div> 15 22 </div> 16 23 17 - <div class="details-panel"> 18 - <dl> 19 - <div> 20 - <dt>Operating system</dt> 21 - <dd>Svelte 5</dd> 22 - </div> 23 - <div> 24 - <dt>Desktop environment</dt> 25 - <dd>GNOME 2</dd> 26 - </div> 27 - <div> 28 - <dt>Protocol</dt> 29 - <dd>at://</dd> 30 - </div> 31 - <div> 32 - <dt>Version</dt> 33 - <dd>{buildVersion.version}</dd> 34 - </div> 35 - <div> 36 - <dt>Commit</dt> 37 - <dd class="mono"> 38 - <a href={buildCommitUrl} target="_blank" rel="external">{buildVersion.commit}</a> 39 - </dd> 40 - </div> 41 - <div> 42 - <dt>Account</dt> 43 - <dd>{accountSetup.identity ? `@${accountSetup.identity.handle}` : 'No account configured'}</dd> 44 - </div> 45 - <div> 46 - <dt>DID</dt> 47 - <dd class="mono">{accountSetup.identity?.did ?? '—'}</dd> 48 - </div> 49 - <div> 50 - <dt>PDS</dt> 51 - <dd class="mono">{accountSetup.identity?.pds ?? '—'}</dd> 52 - </div> 53 - </dl> 24 + <div class="details-grid"> 25 + <section class="details-panel" aria-labelledby="system-title"> 26 + <h3 id="system-title">System</h3> 27 + <dl> 28 + <div> 29 + <dt>Operating System*</dt> 30 + <dd>Intrepid Ibex (Ubuntu 8.10)</dd> 31 + </div> 32 + <div> 33 + <dt>Desktop Environment</dt> 34 + <dd>GNOME 2</dd> 35 + </div> 36 + <div> 37 + <dt>GTK Theme</dt> 38 + <dd>Ubuntu 8.10 Human</dd> 39 + </div> 40 + <div> 41 + <dt>Icon Theme</dt> 42 + <dd>Humanity</dd> 43 + </div> 44 + <div> 45 + <dt>Protocol</dt> 46 + <dd>at://</dd> 47 + </div> 48 + <div> 49 + <dt>Version</dt> 50 + <dd>{buildVersion.version}</dd> 51 + </div> 52 + <div> 53 + <dt>Commit</dt> 54 + <dd class="mono"> 55 + <a href={buildCommitUrl} target="_blank" rel="external">{buildVersion.commit}</a> 56 + </dd> 57 + </div> 58 + </dl> 59 + </section> 60 + 61 + <section class="details-panel" aria-labelledby="repo-title"> 62 + <h3 id="repo-title">Public Repository</h3> 63 + {#if identity} 64 + <div class="identity-card"> 65 + <img src={identity.avatar ?? '/icons/humanity/apps/identity-inspector.svg'} alt="" width="48" height="48" /> 66 + <div> 67 + <strong>{profileName}</strong> 68 + <span>@{identity.handle}</span> 69 + </div> 70 + </div> 71 + {:else} 72 + <p class="empty-state">No public repository is configured yet.</p> 73 + {/if} 74 + 75 + <dl> 76 + <div> 77 + <dt>Source</dt> 78 + <dd>{repositorySource}</dd> 79 + </div> 80 + <div> 81 + <dt>Handle</dt> 82 + <dd>{repositoryHandle}</dd> 83 + </div> 84 + <div> 85 + <dt>DID</dt> 86 + <dd class="mono">{identity?.did ?? '—'}</dd> 87 + </div> 88 + <div> 89 + <dt>PDS</dt> 90 + <dd class="mono">{identity?.pds ?? 'Not advertised'}</dd> 91 + </div> 92 + <div> 93 + <dt>Display name</dt> 94 + <dd>{identity?.displayName ?? 'Not set'}</dd> 95 + </div> 96 + <div> 97 + <dt>Description</dt> 98 + <dd>{identity?.description ?? 'Not set'}</dd> 99 + </div> 100 + </dl> 101 + </section> 102 + </div> 103 + 104 + <div class="status-strip" aria-label="System status"> 105 + <div> 106 + <span>Cache</span> 107 + <a href="https://dexie.org/" target="_blank"><strong>IndexedDb</strong></a> 108 + </div> 109 + <div> 110 + <span>Network</span> 111 + <a href="https://atproto.com/" target="_blank"><strong>ATmosphere</strong></a> 112 + </div> 113 + <div> 114 + <span>Login</span> 115 + <strong>No authentication required</strong> 116 + </div> 54 117 </div> 55 118 56 119 <p class="note"> ··· 58 121 <a href={REPO_URL} target="_blank" rel="external">Tangled</a>. Atmosphere logos courtesy of 59 122 <a href="https://tangled.org/cozylittle.house/atmologos" target="_blank" rel="noreferrer">atmologos</a>. 60 123 </p> 124 + <p class="note"><em>*not really</em></p> 61 125 </section> 62 126 63 127 <style> ··· 66 130 gap: var(--space-4); 67 131 height: 100%; 68 132 padding: var(--space-5); 133 + overflow: auto; 69 134 background: 70 135 radial-gradient(circle at 18% 18%, rgb(244 186 98 / 0.35), transparent 10rem), linear-gradient(#fff8eb, #decaac); 71 136 } ··· 100 165 line-height: var(--leading-tight); 101 166 } 102 167 168 + h3 { 169 + margin-bottom: var(--space-3); 170 + padding: var(--space-1) var(--space-2); 171 + color: #fff8ea; 172 + font-size: var(--text-1); 173 + background: linear-gradient(#7b5733, #4f321e); 174 + border: 1px solid #3d2415; 175 + border-radius: var(--radius-1); 176 + text-shadow: 0 1px 0 rgb(0 0 0 / 0.65); 177 + } 178 + 103 179 .hero p:last-child, 104 180 .note { 105 181 margin-top: var(--space-1); ··· 107 183 font-size: var(--text-2); 108 184 } 109 185 110 - .details-panel { 111 - padding: var(--space-4); 186 + .details-grid { 187 + display: grid; 188 + gap: var(--space-4); 189 + } 190 + 191 + .details-panel, 192 + .status-strip { 193 + padding: var(--space-3); 112 194 background: #fffdf7; 113 195 border: 1px solid #b29165; 114 196 border-radius: var(--radius-2); 115 197 box-shadow: var(--shadow-sunken); 116 198 } 117 199 200 + .identity-card { 201 + display: grid; 202 + grid-template-columns: 48px minmax(0, 1fr); 203 + gap: var(--space-3); 204 + align-items: center; 205 + margin-bottom: var(--space-3); 206 + padding: var(--space-2); 207 + background: linear-gradient(#fff8e8, #ead9bd); 208 + border: 1px solid #c2a072; 209 + border-radius: var(--radius-2); 210 + } 211 + 212 + .identity-card img { 213 + border: 1px solid #8e6d43; 214 + border-radius: var(--radius-1); 215 + object-fit: cover; 216 + background: #f4e4c8; 217 + } 218 + 219 + .identity-card div { 220 + display: grid; 221 + gap: 0.1rem; 222 + min-width: 0; 223 + } 224 + 225 + .identity-card strong, 226 + .identity-card span { 227 + overflow: hidden; 228 + text-overflow: ellipsis; 229 + white-space: nowrap; 230 + } 231 + 232 + .identity-card span, 233 + .empty-state { 234 + color: var(--text-muted); 235 + font-size: var(--text-1); 236 + } 237 + 118 238 dl { 119 239 display: grid; 120 240 gap: var(--space-2); ··· 122 242 123 243 dl div { 124 244 display: grid; 125 - grid-template-columns: 10rem minmax(0, 1fr); 245 + grid-template-columns: 8.5rem minmax(0, 1fr); 126 246 gap: var(--space-3); 247 + padding-bottom: var(--space-2); 248 + border-bottom: 1px solid #ead9bd; 249 + } 250 + 251 + dl div:last-child { 252 + padding-bottom: 0; 253 + border-bottom: 0; 127 254 } 128 255 129 256 dt { ··· 147 274 text-decoration: underline; 148 275 } 149 276 277 + .status-strip { 278 + display: grid; 279 + grid-template-columns: repeat(3, minmax(0, 1fr)); 280 + gap: var(--space-2); 281 + } 282 + 283 + .status-strip div { 284 + display: grid; 285 + gap: 0.1rem; 286 + padding: var(--space-2); 287 + background: linear-gradient(#f8ecd5, #e2caa5); 288 + border: 1px solid #c2a072; 289 + border-radius: var(--radius-1); 290 + } 291 + 292 + .status-strip span { 293 + color: var(--text-muted); 294 + font-size: var(--text-0); 295 + font-weight: 700; 296 + text-transform: uppercase; 297 + } 298 + 299 + .status-strip strong { 300 + overflow-wrap: anywhere; 301 + font-size: var(--text-1); 302 + } 303 + 150 304 .note { 151 305 align-self: end; 152 306 } ··· 157 311 text-decoration: underline; 158 312 } 159 313 160 - @media (max-width: 640px) { 314 + @media (max-width: 760px) { 161 315 .about-computer { 162 316 padding: var(--space-3); 163 317 } 164 318 165 319 .hero, 320 + .details-grid, 321 + .status-strip, 166 322 dl div { 167 323 grid-template-columns: 1fr; 168 324 }