atproto explorer

validate handles in identity tab

handle.invalid 0492e5e9 5c04389f

verified
+50 -31
+2 -27
src/components/navbar.tsx
··· 1 - import { Did, Handle } from "@atcute/lexicons"; 2 import { A, Params, useLocation } from "@solidjs/router"; 3 import { createEffect, createSignal, Show } from "solid-js"; 4 - import { didDocCache, labelerCache, validateHandle } from "../utils/api"; 5 import { CopyMenu, DropdownMenu, MenuProvider } from "./dropdown"; 6 import Tooltip from "./tooltip"; 7 ··· 29 const NavBar = (props: { params: Params }) => { 30 const location = useLocation(); 31 const [handle, setHandle] = createSignal(props.params.repo); 32 - const [validHandle, setValidHandle] = createSignal<boolean | undefined>(undefined); 33 const [fullCid, setFullCid] = createSignal(false); 34 const [showHandle, setShowHandle] = createSignal(localStorage.showHandle === "true"); 35 ··· 43 didDocCache[props.params.repo]?.alsoKnownAs 44 ?.filter((alias) => alias.startsWith("at://"))[0] 45 .split("at://")[1] ?? props.params.repo; 46 - if (hdl !== handle() || validHandle() === undefined) { 47 - setValidHandle(undefined); 48 - setHandle(hdl); 49 - setValidHandle(await validateHandle(hdl as Handle, props.params.repo as Did)); 50 - } 51 } 52 }); 53 ··· 112 {showHandle() ? handle() : props.params.repo} 113 </A> 114 : <span>{showHandle() ? handle() : props.params.repo}</span>} 115 - <Show when={showHandle()}> 116 - <Tooltip 117 - text={ 118 - validHandle() === true ? "Valid handle" 119 - : validHandle() === undefined ? 120 - "Validating" 121 - : "Invalid handle" 122 - } 123 - > 124 - <span 125 - classList={{ 126 - "iconify lucide--circle-check": validHandle() === true, 127 - "iconify lucide--circle-x text-red-500 dark:text-red-400": 128 - validHandle() === false, 129 - "iconify lucide--loader-circle animate-spin": validHandle() === undefined, 130 - }} 131 - ></span> 132 - </Tooltip> 133 - </Show> 134 </div> 135 </div> 136 <Tooltip text={showHandle() ? "Show DID" : "Show handle"}>
··· 1 import { A, Params, useLocation } from "@solidjs/router"; 2 import { createEffect, createSignal, Show } from "solid-js"; 3 + import { didDocCache, labelerCache } from "../utils/api"; 4 import { CopyMenu, DropdownMenu, MenuProvider } from "./dropdown"; 5 import Tooltip from "./tooltip"; 6 ··· 28 const NavBar = (props: { params: Params }) => { 29 const location = useLocation(); 30 const [handle, setHandle] = createSignal(props.params.repo); 31 const [fullCid, setFullCid] = createSignal(false); 32 const [showHandle, setShowHandle] = createSignal(localStorage.showHandle === "true"); 33 ··· 41 didDocCache[props.params.repo]?.alsoKnownAs 42 ?.filter((alias) => alias.startsWith("at://"))[0] 43 .split("at://")[1] ?? props.params.repo; 44 + if (hdl !== handle()) setHandle(hdl); 45 } 46 }); 47 ··· 106 {showHandle() ? handle() : props.params.repo} 107 </A> 108 : <span>{showHandle() ? handle() : props.params.repo}</span>} 109 </div> 110 </div> 111 <Tooltip text={showHandle() ? "Show DID" : "Show handle"}>
+48 -4
src/views/repo.tsx
··· 7 processIndexedEntryLog, 8 } from "@atcute/did-plc"; 9 import { DidDocument } from "@atcute/identity"; 10 - import { ActorIdentifier, Handle } from "@atcute/lexicons"; 11 import { A, useLocation, useNavigate, useParams } from "@solidjs/router"; 12 - import { createResource, createSignal, ErrorBoundary, For, Show, Suspense } from "solid-js"; 13 import { Backlinks } from "../components/backlinks.jsx"; 14 import { Button } from "../components/button.jsx"; 15 import { TextInput } from "../components/text-input.jsx"; 16 import Tooltip from "../components/tooltip.jsx"; 17 - import { didDocCache, resolveHandle, resolvePDS } from "../utils/api.js"; 18 import { localDateFromTimestamp } from "../utils/date.js"; 19 import { createOperationHistory, DiffEntry, groupBy } from "../utils/plc-logs.js"; 20 import { BlobView } from "./blob.jsx"; ··· 164 const [showPlcLogs, setShowPlcLogs] = createSignal(false); 165 const [loading, setLoading] = createSignal(false); 166 const [notice, setNotice] = createSignal<string>(); 167 let rpc: Client; 168 let pds: string; 169 const did = params.repo; ··· 264 [authority]: { ...nsids()![authority], hidden: !nsids()![authority].hidden }, 265 }); 266 }; 267 268 return ( 269 <Show when={repo()}> ··· 410 </div> 411 <ul> 412 <For each={didDocument().alsoKnownAs}> 413 - {(alias) => <li class="text-sm">{alias}</li>} 414 </For> 415 </ul> 416 </div>
··· 7 processIndexedEntryLog, 8 } from "@atcute/did-plc"; 9 import { DidDocument } from "@atcute/identity"; 10 + import { ActorIdentifier, Did, Handle } from "@atcute/lexicons"; 11 import { A, useLocation, useNavigate, useParams } from "@solidjs/router"; 12 + import { 13 + createEffect, 14 + createResource, 15 + createSignal, 16 + ErrorBoundary, 17 + For, 18 + Show, 19 + Suspense, 20 + } from "solid-js"; 21 + import { createStore } from "solid-js/store"; 22 import { Backlinks } from "../components/backlinks.jsx"; 23 import { Button } from "../components/button.jsx"; 24 import { TextInput } from "../components/text-input.jsx"; 25 import Tooltip from "../components/tooltip.jsx"; 26 + import { didDocCache, resolveHandle, resolvePDS, validateHandle } from "../utils/api.js"; 27 import { localDateFromTimestamp } from "../utils/date.js"; 28 import { createOperationHistory, DiffEntry, groupBy } from "../utils/plc-logs.js"; 29 import { BlobView } from "./blob.jsx"; ··· 173 const [showPlcLogs, setShowPlcLogs] = createSignal(false); 174 const [loading, setLoading] = createSignal(false); 175 const [notice, setNotice] = createSignal<string>(); 176 + const [validHandles, setValidHandles] = createStore<Record<string, boolean>>({}); 177 let rpc: Client; 178 let pds: string; 179 const did = params.repo; ··· 274 [authority]: { ...nsids()![authority], hidden: !nsids()![authority].hidden }, 275 }); 276 }; 277 + 278 + createEffect(async () => { 279 + for (const alias of didDoc()?.alsoKnownAs ?? []) { 280 + if (alias.startsWith("at://")) 281 + setValidHandles( 282 + alias, 283 + await validateHandle(alias.replace("at://", "") as Handle, did as Did), 284 + ); 285 + } 286 + }); 287 288 return ( 289 <Show when={repo()}> ··· 430 </div> 431 <ul> 432 <For each={didDocument().alsoKnownAs}> 433 + {(alias) => ( 434 + <li class="flex items-center gap-1 text-sm"> 435 + <span>{alias}</span> 436 + <Show when={alias.startsWith("at://")}> 437 + <Tooltip 438 + text={ 439 + validHandles[alias] === true ? "Valid handle" 440 + : validHandles[alias] === undefined ? 441 + "Validating" 442 + : "Invalid handle" 443 + } 444 + > 445 + <span 446 + classList={{ 447 + "iconify lucide--circle-check": validHandles[alias] === true, 448 + "iconify lucide--circle-x text-red-500 dark:text-red-400": 449 + validHandles[alias] === false, 450 + "iconify lucide--loader-circle animate-spin": 451 + validHandles[alias] === undefined, 452 + }} 453 + ></span> 454 + </Tooltip> 455 + </Show> 456 + </li> 457 + )} 458 </For> 459 </ul> 460 </div>