An easy-to-host PDS on the ATProtocol, iPhone and MacOS. Maintain control of your keys and data, always.
1
fork

Configure Feed

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

feat(identity-wallet): add ClaimSuccessScreen component

Implements a success screen that displays the updated DID document summary
after claim submission. Extracts DID, handle, and PDS endpoint from the
updatedDidDoc and shows them in a summary card. Verifies plc-key-management.AC5.12.

authored by

Malpercio and committed by
Tangled
c1339556 114d2b9a

+177
+177
apps/identity-wallet/src/lib/components/onboarding/ClaimSuccessScreen.svelte
··· 1 + <script lang="ts"> 2 + import { type ClaimResult } from '$lib/ipc'; 3 + 4 + let { 5 + claimResult, 6 + ondone, 7 + }: { 8 + claimResult: ClaimResult; 9 + ondone: () => void; 10 + } = $props(); 11 + 12 + // Extract typed fields from the loosely-typed updatedDidDoc 13 + let didId = $derived( 14 + typeof claimResult.updatedDidDoc?.id === 'string' 15 + ? claimResult.updatedDidDoc.id 16 + : '—' 17 + ); 18 + 19 + let alsoKnownAs = $derived( 20 + Array.isArray(claimResult.updatedDidDoc?.alsoKnownAs) 21 + ? (claimResult.updatedDidDoc.alsoKnownAs as string[]) 22 + : [] 23 + ); 24 + 25 + let pdsEndpoint = $derived.by(() => { 26 + const services = claimResult.updatedDidDoc?.service; 27 + if (!Array.isArray(services)) return '—'; 28 + 29 + const pdsService = services.find( 30 + (svc) => 31 + typeof svc === 'object' && 32 + svc !== null && 33 + (svc as Record<string, unknown>)?.type === 'AtprotoPersonalDataServer' 34 + ); 35 + 36 + if (pdsService && typeof (pdsService as Record<string, unknown>)?.serviceEndpoint === 'string') { 37 + return (pdsService as Record<string, unknown>).serviceEndpoint as string; 38 + } 39 + 40 + return '—'; 41 + }); 42 + </script> 43 + 44 + <div class="screen"> 45 + <!-- Success header --> 46 + <div class="header"> 47 + <div class="checkmark-circle">✓</div> 48 + <h2 class="title">Identity Claimed Successfully</h2> 49 + <p class="subtitle">Your rotation key has been updated. You are now in control of this identity.</p> 50 + </div> 51 + 52 + <!-- DID document summary --> 53 + <div class="summary-card"> 54 + <div class="summary-item"> 55 + <p class="summary-label">DID</p> 56 + <code class="summary-value">{didId}</code> 57 + </div> 58 + 59 + {#if alsoKnownAs.length > 0} 60 + <div class="summary-item"> 61 + <p class="summary-label">Handle</p> 62 + <p class="summary-value">{alsoKnownAs[0]}</p> 63 + </div> 64 + {/if} 65 + 66 + <div class="summary-item"> 67 + <p class="summary-label">PDS Endpoint</p> 68 + <p class="summary-value mono">{pdsEndpoint}</p> 69 + </div> 70 + </div> 71 + 72 + <!-- Done button --> 73 + <button class="cta" onclick={ondone}>Done</button> 74 + </div> 75 + 76 + <style> 77 + .screen { 78 + display: flex; 79 + flex-direction: column; 80 + align-items: center; 81 + justify-content: center; 82 + height: 100%; 83 + padding: 2rem; 84 + gap: 2rem; 85 + text-align: center; 86 + } 87 + 88 + .header { 89 + display: flex; 90 + flex-direction: column; 91 + align-items: center; 92 + gap: 1rem; 93 + } 94 + 95 + .checkmark-circle { 96 + width: 64px; 97 + height: 64px; 98 + background: #22c55e; 99 + color: #fff; 100 + border-radius: 50%; 101 + display: flex; 102 + align-items: center; 103 + justify-content: center; 104 + font-size: 2rem; 105 + font-weight: 700; 106 + } 107 + 108 + .title { 109 + font-size: 1.5rem; 110 + font-weight: 700; 111 + color: #111827; 112 + margin: 0; 113 + } 114 + 115 + .subtitle { 116 + font-size: 0.95rem; 117 + color: #6b7280; 118 + margin: 0; 119 + max-width: 300px; 120 + line-height: 1.5; 121 + } 122 + 123 + .summary-card { 124 + background: #f9fafb; 125 + border: 1px solid #d1d5db; 126 + border-radius: 12px; 127 + padding: 1.5rem; 128 + width: 100%; 129 + max-width: 400px; 130 + display: flex; 131 + flex-direction: column; 132 + gap: 1rem; 133 + } 134 + 135 + .summary-item { 136 + display: flex; 137 + flex-direction: column; 138 + gap: 0.25rem; 139 + align-items: flex-start; 140 + width: 100%; 141 + } 142 + 143 + .summary-label { 144 + font-size: 0.75rem; 145 + font-weight: 600; 146 + color: #6b7280; 147 + margin: 0; 148 + text-transform: uppercase; 149 + letter-spacing: 0.05em; 150 + } 151 + 152 + .summary-value { 153 + font-size: 0.9rem; 154 + color: #374151; 155 + margin: 0; 156 + word-break: break-all; 157 + text-align: left; 158 + } 159 + 160 + .summary-value.mono { 161 + font-family: monospace; 162 + font-size: 0.8rem; 163 + } 164 + 165 + .cta { 166 + width: 100%; 167 + max-width: 320px; 168 + padding: 1rem; 169 + background: #007aff; 170 + color: #fff; 171 + border: none; 172 + border-radius: 12px; 173 + font-size: 1rem; 174 + font-weight: 600; 175 + cursor: pointer; 176 + } 177 + </style>