atmosphere explorer

add alt bsky clients

handle.invalid 80fefdb0 1180024a

verified
+75 -15
+75 -15
src/views/record.tsx
··· 8 8 import { verifyRecord } from "@atcute/repo"; 9 9 import { Title } from "@solidjs/meta"; 10 10 import { A, useLocation, useNavigate, useParams } from "@solidjs/router"; 11 - import { createResource, createSignal, ErrorBoundary, Show, Suspense } from "solid-js"; 11 + import { createResource, createSignal, ErrorBoundary, For, Show, Suspense } from "solid-js"; 12 12 import { agent } from "../auth/state"; 13 13 import { Backlinks } from "../components/backlinks.jsx"; 14 14 import { Button } from "../components/button.jsx"; ··· 36 36 import { clearCollectionCache } from "../utils/route-cache.js"; 37 37 import { AtUri, uriTemplates } from "../utils/templates.js"; 38 38 import { lexicons } from "../utils/types/lexicons.js"; 39 + 40 + const toAuthority = (hostname: string) => hostname.split(".").reverse().join("."); 41 + 42 + const faviconWrapper = (children: any) => ( 43 + <div class="flex size-4 items-center justify-center">{children}</div> 44 + ); 45 + 46 + const bskyAltClients = [ 47 + { 48 + label: "Blacksky", 49 + hostname: "blacksky.app", 50 + transform: (url: string) => url.replace("https://bsky.app", "https://blacksky.community"), 51 + }, 52 + { 53 + label: "Witchsky", 54 + hostname: "witchsky.app", 55 + transform: (url: string) => url.replace("https://bsky.app", "https://witchsky.app"), 56 + }, 57 + { 58 + label: "Anartia", 59 + hostname: "kelinci.net", 60 + icon: "https://kelinci.net/rabbit.svg", 61 + transform: (url: string) => 62 + url.replace("https://bsky.app/profile", "https://anartia.kelinci.net").replace("/post/", "/"), 63 + }, 64 + ]; 39 65 40 66 const authorityCache = new Map<string, Promise<AtprotoDid>>(); 41 67 const documentCache = new Map<string, Promise<DidDocument>>(); ··· 191 217 const navigate = useNavigate(); 192 218 const params = useParams(); 193 219 const [openDelete, setOpenDelete] = createSignal(false); 220 + const [showAlternates, setShowAlternates] = createSignal(false); 194 221 const [verifyError, setVerifyError] = createSignal(""); 195 222 const [validationError, setValidationError] = createSignal(""); 196 223 const [externalLink, setExternalLink] = createSignal< ··· 438 465 </Modal> 439 466 </Show> 440 467 <Show when={externalLink()}> 441 - {(link) => ( 442 - <a 443 - href={link().link} 444 - target="_blank" 445 - class="flex rounded-sm p-1.5 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600" 446 - > 447 - <Favicon 448 - authority={new URL(link().link).hostname.split(".").reverse().join(".")} 449 - wrapper={(children) => ( 450 - <div class="flex size-4 items-center justify-center">{children}</div> 451 - )} 452 - /> 453 - </a> 454 - )} 468 + {(link) => { 469 + const bskyAlts = () => 470 + link().link.startsWith("https://bsky.app") ? 471 + bskyAltClients.map((alt) => ({ ...alt, link: alt.transform(link().link) })) 472 + : []; 473 + return ( 474 + <div 475 + class="relative" 476 + onMouseEnter={() => setShowAlternates(true)} 477 + onMouseLeave={() => setShowAlternates(false)} 478 + > 479 + <a 480 + href={link().link} 481 + target="_blank" 482 + title={`Open on ${link().label}`} 483 + class="flex rounded-sm p-1.5 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600" 484 + > 485 + <Favicon 486 + authority={toAuthority(new URL(link().link).hostname)} 487 + wrapper={faviconWrapper} 488 + /> 489 + </a> 490 + <Show when={showAlternates() && bskyAlts().length > 0}> 491 + <div class="dark:bg-dark-500 absolute top-full left-0 z-10 flex flex-col rounded bg-neutral-100"> 492 + <For each={bskyAlts()}> 493 + {(alt) => ( 494 + <a 495 + href={alt.link} 496 + target="_blank" 497 + title={`Open on ${alt.label}`} 498 + class="flex rounded-sm p-1.5 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600" 499 + > 500 + {alt.icon ? 501 + <img src={alt.icon} class="size-4" /> 502 + : <Favicon 503 + authority={toAuthority(alt.hostname)} 504 + wrapper={faviconWrapper} 505 + /> 506 + } 507 + </a> 508 + )} 509 + </For> 510 + </div> 511 + </Show> 512 + </div> 513 + ); 514 + }} 455 515 </Show> 456 516 <MenuProvider> 457 517 <DropdownMenu icon="lucide--ellipsis" buttonClass="rounded-sm p-1.5">