atproto explorer
0
fork

Configure Feed

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

switch account without reloading

Juliet dad51a8b ad2ca5fd

+29 -32
+8 -7
src/components/account.tsx
··· 1 1 import { createSignal, onMount, For, Show } from "solid-js"; 2 2 import Tooltip from "./tooltip.jsx"; 3 3 import { deleteStoredSession, getSession, OAuthUserAgent } from "@atcute/oauth-browser-client"; 4 - import { agent, Login, loginState, retrieveSession, setLoginState } from "./login.jsx"; 4 + import { agent, Login, retrieveSession, setAgent } from "./login.jsx"; 5 5 import { Did } from "@atcute/lexicons"; 6 6 import { resolveDidDoc } from "../utils/api.js"; 7 7 import { createStore } from "solid-js/store"; ··· 35 35 if (repo) setAvatar(await getAvatar(repo as Did)); 36 36 }); 37 37 38 - const resumeSession = (did: Did) => { 38 + const resumeSession = async (did: Did) => { 39 39 localStorage.setItem("lastSignedIn", did); 40 - window.location.href = "/"; 40 + retrieveSession(); 41 + setAvatar(await getAvatar(did)); 41 42 }; 42 43 43 44 const removeSession = async (did: Did) => { 44 - const currentSession = agent?.sub; 45 + const currentSession = agent()?.sub; 45 46 try { 46 47 const session = await getSession(did, { allowStale: true }); 47 48 const agent = new OAuthUserAgent(session); ··· 50 51 deleteStoredSession(did); 51 52 } 52 53 setSessions(did, undefined); 53 - if (currentSession === did) setLoginState(false); 54 + if (currentSession === did) setAgent(undefined); 54 55 }; 55 56 56 57 const getAvatar = async (did: Did) => { ··· 78 79 onclick={() => resumeSession(did as Did)} 79 80 > 80 81 <span class="truncate">{sessions[did]?.length ? sessions[did] : did}</span> 81 - <Show when={did === agent?.sub}> 82 + <Show when={did === agent()?.sub}> 82 83 <div class="i-lucide-check shrink-0" /> 83 84 </Show> 84 85 </button> ··· 94 95 </Modal> 95 96 <button onclick={() => setOpenManager(true)}> 96 97 <Tooltip text="Accounts"> 97 - {loginState() && avatar() ? 98 + {agent() && avatar() ? 98 99 <img src={avatar()} class="dark:shadow-dark-900/80 size-5 rounded-full shadow-sm" /> 99 100 : <div class="i-lucide-circle-user-round text-xl" />} 100 101 </Tooltip>
+6 -6
src/components/create.tsx
··· 37 37 }; 38 38 39 39 const createRecord = async (formData: FormData) => { 40 - const rpc = new Client({ handler: agent }); 40 + const rpc = new Client({ handler: agent()! }); 41 41 const collection = formData.get("collection"); 42 42 const rkey = formData.get("rkey"); 43 43 const validate = formData.get("validate")?.toString(); ··· 50 50 } 51 51 const res = await rpc.post("com.atproto.repo.createRecord", { 52 52 input: { 53 - repo: agent.sub, 53 + repo: agent()!.sub, 54 54 collection: collection ? collection.toString() : record.$type, 55 55 rkey: rkey?.toString().length ? rkey?.toString() : undefined, 56 56 record: record, ··· 75 75 : formData.get("validate")?.toString() === "false" ? false 76 76 : undefined; 77 77 if (!record) return; 78 - const rpc = new Client({ handler: agent }); 78 + const rpc = new Client({ handler: agent()! }); 79 79 try { 80 80 const editedRecord = JSON.parse(record.toString()); 81 81 if (formData.get("recreate")) { 82 82 const res = await rpc.post("com.atproto.repo.applyWrites", { 83 83 input: { 84 - repo: agent.sub, 84 + repo: agent()!.sub, 85 85 validate: validate, 86 86 writes: [ 87 87 { ··· 105 105 } else { 106 106 const res = await rpc.post("com.atproto.repo.putRecord", { 107 107 input: { 108 - repo: agent.sub, 108 + repo: agent()!.sub, 109 109 collection: params.collection as `${string}.${string}.${string}`, 110 110 rkey: params.rkey, 111 111 record: editedRecord, ··· 141 141 if (exifRemoved !== null) blob = new Blob([exifRemoved], { type: blob.type }); 142 142 } 143 143 144 - const rpc = new Client({ handler: agent }); 144 + const rpc = new Client({ handler: agent()! }); 145 145 setUploading(true); 146 146 const res = await rpc.post("com.atproto.repo.uploadBlob", { 147 147 input: blob,
+3 -7
src/components/login.tsx
··· 21 21 }, 22 22 }); 23 23 24 - export const [loginState, setLoginState] = createSignal(false); 25 - let agent: OAuthUserAgent; 24 + export const [agent, setAgent] = createSignal<OAuthUserAgent | undefined>(); 26 25 27 26 const Login = () => { 28 27 const [notice, setNotice] = createSignal(""); ··· 106 105 107 106 const session = await init().catch(() => {}); 108 107 109 - if (session) { 110 - agent = new OAuthUserAgent(session); 111 - setLoginState(true); 112 - } 108 + if (session) setAgent(new OAuthUserAgent(session)); 113 109 }; 114 110 115 - export { Login, retrieveSession, agent }; 111 + export { Login, retrieveSession };
+3 -3
src/components/search.tsx
··· 2 2 import { A, useNavigate } from "@solidjs/router"; 3 3 import Tooltip from "./tooltip.jsx"; 4 4 import { createSignal, Show } from "solid-js"; 5 - import { agent, loginState } from "../components/login.jsx"; 5 + import { agent } from "../components/login.jsx"; 6 6 import { Handle } from "@atcute/lexicons"; 7 7 8 8 const Search = () => { ··· 72 72 </button> 73 73 </Show> 74 74 </div> 75 - <Show when={loginState()}> 75 + <Show when={agent()}> 76 76 <Tooltip 77 77 text="Repository" 78 78 children={ 79 - <A href={`/at://${agent.sub}`} class="flex"> 79 + <A href={`/at://${agent()?.sub}`} class="flex"> 80 80 <div class="i-lucide-house text-xl" /> 81 81 </A> 82 82 }
+2 -2
src/layout.tsx
··· 1 1 import { createEffect, ErrorBoundary, Show, Suspense } from "solid-js"; 2 2 import { A, RouteSectionProps, useLocation, useNavigate, useParams } from "@solidjs/router"; 3 - import { loginState } from "./components/login.jsx"; 3 + import { agent } from "./components/login.jsx"; 4 4 import { RecordEditor } from "./components/create.jsx"; 5 5 import Tooltip from "./components/tooltip.jsx"; 6 6 import { NavBar } from "./components/navbar.jsx"; ··· 60 60 </Show> 61 61 </div> 62 62 <div class="justify-right flex basis-1/3 items-center gap-x-2"> 63 - <Show when={loginState()}> 63 + <Show when={agent()}> 64 64 <RecordEditor create={true} /> 65 65 </Show> 66 66 <Settings />
+4 -4
src/views/collection.tsx
··· 4 4 import { resolvePDS } from "../utils/api.js"; 5 5 import * as TID from "@atcute/tid"; 6 6 import { JSONType, JSONValue } from "../components/json.jsx"; 7 - import { agent, loginState } from "../components/login.jsx"; 7 + import { agent } from "../components/login.jsx"; 8 8 import { createStore } from "solid-js/store"; 9 9 import Tooltip from "../components/tooltip.jsx"; 10 10 import { localDateFromTimestamp } from "../utils/date.js"; ··· 119 119 }); 120 120 121 121 const BATCHSIZE = 200; 122 - rpc = new Client({ handler: agent }); 122 + rpc = new Client({ handler: agent()! }); 123 123 for (let i = 0; i < writes.length; i += BATCHSIZE) { 124 124 await rpc.post("com.atproto.repo.applyWrites", { 125 125 input: { 126 - repo: agent.sub, 126 + repo: agent()!.sub, 127 127 writes: writes.slice(i, i + BATCHSIZE), 128 128 }, 129 129 }); ··· 159 159 <Show when={records.length || response()}> 160 160 <div class="z-5 dark:bg-dark-500/70 backdrop-blur-xs sticky top-0 flex w-screen flex-col items-center justify-center gap-2 bg-zinc-100/70 py-3"> 161 161 <div class="w-21rem sm:w-24rem flex items-center gap-2"> 162 - <Show when={loginState() && agent.sub === did}> 162 + <Show when={agent() && agent()?.sub === did}> 163 163 <div class="flex items-center gap-x-2"> 164 164 <Tooltip 165 165 text={batchDelete() ? "Cancel" : "Delete"}
+3 -3
src/views/record.tsx
··· 5 5 6 6 import { Backlinks } from "../components/backlinks.jsx"; 7 7 import { JSONValue } from "../components/json.jsx"; 8 - import { agent, loginState } from "../components/login.jsx"; 8 + import { agent } from "../components/login.jsx"; 9 9 import { setCID, setValidRecord, setValidSchema, validRecord } from "../components/navbar.jsx"; 10 10 11 11 import { didDocCache, getAllBacklinks, LinkData, resolvePDS } from "../utils/api.js"; ··· 102 102 }); 103 103 104 104 const deleteRecord = async () => { 105 - rpc = new Client({ handler: agent }); 105 + rpc = new Client({ handler: agent()! }); 106 106 await rpc.post("com.atproto.repo.deleteRecord", { 107 107 input: { 108 108 repo: params.repo as ActorIdentifier, ··· 142 142 <div class="i-lucide-copy text-xl" /> 143 143 </button> 144 144 </Tooltip> 145 - <Show when={loginState() && agent.sub === record()?.uri.split("/")[2]}> 145 + <Show when={agent() && agent()?.sub === record()?.uri.split("/")[2]}> 146 146 <RecordEditor create={false} record={record()?.value} /> 147 147 <div class="relative flex"> 148 148 <Tooltip text="Delete">