atmosphere explorer
0
fork

Configure Feed

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

at main 279 lines 11 kB view raw
1import { A } from "@solidjs/router"; 2import { createSignal, For, JSX, onCleanup, onMount } from "solid-js"; 3import { setOpenManager, setShowAddAccount } from "../auth/state"; 4import { Button } from "../components/button"; 5import { Favicon } from "../components/favicon"; 6import { JSONValue } from "../components/json"; 7import { SearchButton } from "../components/search"; 8 9const SLIDES = ["Repository", "Record", "PDS"] as const; 10 11const slideLinks = [ 12 "/at://did:plc:vwzwgnygau7ed7b7wt5ux7y2", 13 "/at://did:plc:ia76kvnndjutgedggx2ibrem/app.bsky.feed.post/3kenlltlvus2u", 14 "/npmx.social", 15] as const; 16 17const exampleRecord = { 18 text: "ma'am do you know where the petard is, i'd like to hoist myself with it", 19 $type: "app.bsky.feed.post", 20 langs: ["en"], 21 createdAt: "2023-11-20T21:44:21.000Z", 22}; 23 24const exampleCollections = [ 25 { authority: "app.bsky", nsids: ["actor.profile", "feed.post", "feed.like", "graph.follow"] }, 26 { authority: "sh.tangled", nsids: ["actor.profile", "repo.pull"] }, 27 { authority: "place.stream", nsids: ["chat.message"] }, 28]; 29 30const exampleRepos = [ 31 "did:plc:ty2jdjtqqq4jn7kk7p3mpwae", 32 "did:plc:byfvayavc7z2ldyu6bu5myz2", 33 "did:plc:n34gdj7o3o6ktuxp5qfbgllu", 34 "did:plc:vh7y4mqklsu2uui5tlwl42dy", 35 "did:plc:uz76j2yr2ps7apdxtlgqljwk", 36]; 37 38const ExplorerShowcase = () => { 39 const [slide, setSlide] = createSignal(0); 40 41 onMount(() => { 42 const id = setInterval(() => setSlide((s) => (s + 1) % SLIDES.length), 5000); 43 onCleanup(() => clearInterval(id)); 44 }); 45 46 return ( 47 <div class="flex flex-col gap-1.5"> 48 <A 49 href={slideLinks[slide()]} 50 class="relative block h-42 overflow-hidden rounded-lg border border-neutral-200 bg-neutral-50 transition-colors hover:border-neutral-300 dark:border-neutral-700 dark:bg-neutral-800 dark:hover:border-neutral-600" 51 > 52 {/* Collections slide */} 53 <div 54 class="pointer-events-none absolute inset-0 flex flex-col gap-1 overflow-hidden px-3 py-2 text-sm wrap-anywhere transition-opacity duration-700" 55 classList={{ "opacity-0": slide() !== 0 }} 56 > 57 <For each={exampleCollections}> 58 {({ authority, nsids }) => ( 59 <div class="flex items-start gap-2"> 60 <Favicon authority={authority} /> 61 <div class="flex flex-col"> 62 <For each={nsids}> 63 {(nsid) => ( 64 <span> 65 <span class="text-neutral-500 dark:text-neutral-400">{authority}.</span> 66 <span>{nsid}</span> 67 </span> 68 )} 69 </For> 70 </div> 71 </div> 72 )} 73 </For> 74 </div> 75 76 {/* Record slide */} 77 <div 78 class="pointer-events-none absolute inset-0 overflow-hidden px-3 py-2 font-mono text-xs wrap-anywhere whitespace-pre-wrap transition-opacity duration-700 sm:text-sm" 79 classList={{ "opacity-0": slide() !== 1 }} 80 > 81 <JSONValue data={exampleRecord as any} repo="did:plc:ia76kvnndjutgedggx2ibrem" /> 82 </div> 83 84 {/* Repos slide */} 85 <div 86 class="pointer-events-none absolute inset-0 overflow-hidden py-0.5 transition-opacity duration-700" 87 classList={{ "opacity-0": slide() !== 2 }} 88 > 89 <For each={exampleRepos}> 90 {(did) => ( 91 <div class="flex min-w-0 items-center gap-2 p-1.5 font-mono text-sm"> 92 <span class="flex shrink-0 items-center text-neutral-400 dark:text-neutral-500"> 93 <span class="iconify lucide--chevron-right" /> 94 </span> 95 <span class="truncate text-blue-500 dark:text-blue-400">{did}</span> 96 </div> 97 )} 98 </For> 99 </div> 100 </A> 101 102 {/* Slide indicator */} 103 <div class="flex items-center justify-between px-0.5"> 104 <span class="text-xs text-neutral-400 dark:text-neutral-500">{SLIDES[slide()]}</span> 105 <div class="flex gap-1"> 106 <For each={SLIDES}> 107 {(_, i) => ( 108 <button 109 onClick={() => setSlide(i())} 110 class="h-1 rounded-full transition-all duration-300" 111 classList={{ 112 "w-4 bg-neutral-400 dark:bg-neutral-500": slide() === i(), 113 "w-1.5 bg-neutral-300 dark:bg-neutral-600": slide() !== i(), 114 }} 115 /> 116 )} 117 </For> 118 </div> 119 </div> 120 </div> 121 ); 122}; 123 124export const Home = () => { 125 const FooterLink = (props: { 126 href: string; 127 color: string; 128 darkColor?: string; 129 children: JSX.Element; 130 }) => ( 131 <a 132 href={props.href} 133 class={`relative flex items-center gap-1.5 after:absolute after:bottom-0 after:left-0 after:h-px after:w-0 after:bg-current ${props.color} after:transition-[width] after:duration-300 after:ease-out hover:after:w-full ${props.darkColor ?? ""}`} 134 target="_blank" 135 > 136 {props.children} 137 </a> 138 ); 139 140 return ( 141 <div class="flex w-full flex-col gap-5 px-2 wrap-break-word"> 142 {/* Welcome Section */} 143 <div class="flex flex-col gap-4"> 144 <div class="flex flex-col gap-1"> 145 <h1 class="text-lg font-medium">Atmosphere Explorer</h1> 146 <div class="text-sm text-neutral-600 dark:text-neutral-300"> 147 <p> 148 Browse the public data on the{" "} 149 <a 150 href="https://atproto.com" 151 target="_blank" 152 class="underline decoration-neutral-400 transition-colors hover:text-blue-500 hover:decoration-blue-500 dark:decoration-neutral-500 dark:hover:text-blue-400" 153 > 154 AT Protocol 155 </a> 156 </p> 157 </div> 158 </div> 159 160 <ExplorerShowcase /> 161 162 <div class="flex items-center gap-1.5 text-xs text-neutral-500 dark:text-neutral-400"> 163 <SearchButton /> 164 <span>to find any account</span> 165 </div> 166 <div class="flex items-center gap-1.5 text-xs text-neutral-500 dark:text-neutral-400"> 167 <Button 168 onClick={() => { 169 setOpenManager(true); 170 setShowAddAccount(true); 171 }} 172 > 173 <span class="iconify lucide--user-round"></span> 174 Sign in 175 </Button> 176 <span>to manage records</span> 177 </div> 178 </div> 179 180 <div class="flex flex-col gap-4 text-sm"> 181 <div class="flex flex-col gap-2"> 182 <A 183 href="/jetstream" 184 class="group grid grid-cols-[auto_1fr] items-center gap-x-2 gap-y-0.5 text-neutral-700 transition-colors hover:text-blue-500 dark:text-neutral-300 dark:hover:text-blue-400" 185 > 186 <div class="iconify lucide--radio-tower" /> 187 <span class="underline decoration-transparent group-hover:decoration-current"> 188 Jetstream 189 </span> 190 <div /> 191 <span class="text-xs text-neutral-500 dark:text-neutral-400"> 192 Event stream with filtering 193 </span> 194 </A> 195 <A 196 href="/firehose" 197 class="group grid grid-cols-[auto_1fr] items-center gap-x-2 gap-y-0.5 text-neutral-700 transition-colors hover:text-blue-500 dark:text-neutral-300 dark:hover:text-blue-400" 198 > 199 <div class="iconify lucide--rss" /> 200 <span class="underline decoration-transparent group-hover:decoration-current"> 201 Firehose 202 </span> 203 <div /> 204 <span class="text-xs text-neutral-500 dark:text-neutral-400"> 205 Raw relay event stream 206 </span> 207 </A> 208 <A 209 href="/spacedust" 210 class="group grid grid-cols-[auto_1fr] items-center gap-x-2 gap-y-0.5 text-neutral-700 transition-colors hover:text-blue-500 dark:text-neutral-300 dark:hover:text-blue-400" 211 > 212 <div class="iconify lucide--orbit" /> 213 <span class="underline decoration-transparent group-hover:decoration-current"> 214 Spacedust 215 </span> 216 <div /> 217 <span class="text-xs text-neutral-500 dark:text-neutral-400"> 218 Interaction links stream 219 </span> 220 </A> 221 </div> 222 223 <div class="flex flex-col gap-2"> 224 <A 225 href="/labels" 226 class="group grid grid-cols-[auto_1fr] items-center gap-x-2 gap-y-0.5 text-neutral-700 transition-colors hover:text-blue-500 dark:text-neutral-300 dark:hover:text-blue-400" 227 > 228 <div class="iconify lucide--tag" /> 229 <span class="underline decoration-transparent group-hover:decoration-current"> 230 Labels 231 </span> 232 <div /> 233 <span class="text-xs text-neutral-500 dark:text-neutral-400"> 234 Query labeler services 235 </span> 236 </A> 237 <A 238 href="/car" 239 class="group grid grid-cols-[auto_1fr] items-center gap-x-2 gap-y-0.5 text-neutral-700 transition-colors hover:text-blue-500 dark:text-neutral-300 dark:hover:text-blue-400" 240 > 241 <div class="iconify lucide--folder-archive" /> 242 <span class="underline decoration-transparent group-hover:decoration-current"> 243 Archive 244 </span> 245 <div /> 246 <span class="text-xs text-neutral-500 dark:text-neutral-400"> 247 Explore and unpack CAR files 248 </span> 249 </A> 250 </div> 251 </div> 252 253 <div class="flex justify-center gap-1.5 text-sm text-neutral-600 sm:gap-2 dark:text-neutral-300"> 254 <FooterLink href="https://raycast.com/juliet_philippe/pdsls" color="after:text-[#FF6363]"> 255 <span class="iconify-color i-raycast-light block dark:hidden"></span> 256 <span class="iconify-color i-raycast-dark hidden dark:block"></span> 257 Raycast 258 </FooterLink> 259 260 <FooterLink 261 href="https://bsky.app/profile/did:plc:6q5daed5gutiyerimlrnojnz" 262 color="after:text-[#0085ff]" 263 > 264 <span class="simple-icons--bluesky iconify text-[#0085ff]"></span> 265 Bluesky 266 </FooterLink> 267 268 <FooterLink 269 href="https://tangled.org/did:plc:6q5daed5gutiyerimlrnojnz/pdsls/" 270 color="after:text-black" 271 darkColor="dark:after:text-white" 272 > 273 <span class="iconify i-tangled text-black dark:text-white"></span> 274 Source 275 </FooterLink> 276 </div> 277 </div> 278 ); 279};