atproto explorer pdsls.dev
atproto tool

refetch record after editing

Changed files
+30 -41
src
+2 -2
src/components/create.tsx
···
import { Modal } from "./modal.jsx";
import { Button } from "./button.jsx";
-
export const RecordEditor = (props: { create: boolean; record?: any }) => {
const navigate = useNavigate();
const params = useParams();
const [openDialog, setOpenDialog] = createSignal(false);
···
}
}
setOpenDialog(false);
-
window.location.reload();
} catch (err: any) {
setNotice(err.message);
}
···
import { Modal } from "./modal.jsx";
import { Button } from "./button.jsx";
+
export const RecordEditor = (props: { create: boolean; record?: any; refetch?: any }) => {
const navigate = useNavigate();
const params = useParams();
const [openDialog, setOpenDialog] = createSignal(false);
···
}
}
setOpenDialog(false);
+
props.refetch();
} catch (err: any) {
setNotice(err.message);
}
+5 -8
src/views/blob.tsx
···
const [cursor, setCursor] = createSignal<string>();
let rpc: Client;
-
const listBlobs = (did: string, cursor: string | undefined) =>
-
rpc.get("com.atproto.sync.listBlobs", {
params: {
-
did: did as `did:${string}:${string}`,
limit: LIMIT,
-
cursor: cursor,
},
});
-
-
const fetchBlobs = async () => {
-
if (!rpc) rpc = new Client({ handler: new CredentialManager({ service: props.pds }) });
-
const res = await listBlobs(props.repo, cursor());
if (!res.ok) throw new Error(res.data.error);
if (!res.data.cids) return [];
setCursor(res.data.cids.length < LIMIT ? undefined : res.data.cursor);
···
const [cursor, setCursor] = createSignal<string>();
let rpc: Client;
+
const fetchBlobs = async () => {
+
if (!rpc) rpc = new Client({ handler: new CredentialManager({ service: props.pds }) });
+
const res = await rpc.get("com.atproto.sync.listBlobs", {
params: {
+
did: props.repo as `did:${string}:${string}`,
limit: LIMIT,
+
cursor: cursor(),
},
});
if (!res.ok) throw new Error(res.data.error);
if (!res.data.cids) return [];
setCursor(res.data.cids.length < LIMIT ? undefined : res.data.cursor);
+6 -9
src/views/collection.tsx
···
let pds: string;
let rpc: Client;
-
const listRecords = (did: string, collection: string, cursor: string | undefined) =>
-
rpc.get("com.atproto.repo.listRecords", {
params: {
repo: did as ActorIdentifier,
-
collection: collection as `${string}.${string}.${string}`,
limit: LIMIT,
-
cursor: cursor,
reverse: reverse(),
},
});
-
-
const fetchRecords = async () => {
-
if (!pds) pds = await resolvePDS(did);
-
if (!rpc) rpc = new Client({ handler: new CredentialManager({ service: pds }) });
-
const res = await listRecords(did, params.collection, cursor());
if (!res.ok) throw new Error(res.data.error);
setCursor(res.data.records.length < LIMIT ? undefined : res.data.cursor);
const tmpRecords: AtprotoRecord[] = [];
···
let pds: string;
let rpc: Client;
+
const fetchRecords = async () => {
+
if (!pds) pds = await resolvePDS(did);
+
if (!rpc) rpc = new Client({ handler: new CredentialManager({ service: pds }) });
+
const res = await rpc.get("com.atproto.repo.listRecords", {
params: {
repo: did as ActorIdentifier,
+
collection: params.collection as `${string}.${string}.${string}`,
limit: LIMIT,
+
cursor: cursor(),
reverse: reverse(),
},
});
if (!res.ok) throw new Error(res.data.error);
setCursor(res.data.records.length < LIMIT ? undefined : res.data.cursor);
const tmpRecords: AtprotoRecord[] = [];
+1 -3
src/views/pds.tsx
···
setVersion((res.data as any).version);
};
-
const fetchRepos = async (): Promise<
-
InferXRPCBodyOutput<ComAtprotoSyncListRepos.mainSchema["output"]>
-
> => {
await getVersion();
const describeRes = await rpc.get("com.atproto.server.describeServer");
if (!describeRes.ok) console.error(describeRes.data.error);
···
setVersion((res.data as any).version);
};
+
const fetchRepos = async () => {
await getVersion();
const describeRes = await rpc.get("com.atproto.server.describeServer");
if (!describeRes.ok) console.error(describeRes.data.error);
+16 -19
src/views/record.tsx
···
import { CredentialManager, Client } from "@atcute/client";
import { useNavigate, useParams } from "@solidjs/router";
-
import { createSignal, ErrorBoundary, onMount, Show, Suspense } from "solid-js";
import { Backlinks } from "../components/backlinks.jsx";
import { JSONValue } from "../components/json.jsx";
···
import { didDocCache, resolvePDS } from "../utils/api.js";
import { AtUri, uriTemplates } from "../utils/templates.js";
import { verifyRecord } from "../utils/verify.js";
-
import { ActorIdentifier, InferXRPCBodyOutput, is } from "@atcute/lexicons";
import { lexiconDoc } from "@atcute/lexicon-doc";
-
import { ComAtprotoRepoGetRecord } from "@atcute/atproto";
import { lexicons } from "../utils/types/lexicons.js";
import { RecordEditor } from "../components/create.jsx";
import { addToClipboard } from "../utils/copy.js";
···
export const RecordView = () => {
const navigate = useNavigate();
const params = useParams();
-
const [record, setRecord] =
-
createSignal<InferXRPCBodyOutput<ComAtprotoRepoGetRecord.mainSchema["output"]>>();
const [openDelete, setOpenDelete] = createSignal(false);
const [notice, setNotice] = createSignal("");
const [showBacklinks, setShowBacklinks] = createSignal(false);
···
const did = params.repo;
let rpc: Client;
-
onMount(async () => {
setCID(undefined);
setValidRecord(undefined);
setValidSchema(undefined);
···
setNotice(res.data.error);
throw new Error(res.data.error);
}
-
setRecord(res.data);
setCID(res.data.cid);
setExternalLink(checkUri(res.data.uri, res.data.value));
···
console.error(err);
setValidRecord(false);
}
-
});
const deleteRecord = async () => {
rpc = new Client({ handler: agent()! });
···
};
return (
-
<div class="flex w-full flex-col items-center">
-
<Show when={record() === undefined && validRecord() !== false}>
-
<div class="iconify lucide--loader-circle mt-3 animate-spin text-xl" />
-
</Show>
-
<Show when={validRecord() === false}>
-
<div class="mt-3 break-words text-red-500 dark:text-red-400">{notice()}</div>
-
</Show>
-
<Show when={record()}>
<div class="dark:shadow-dark-900/80 dark:bg-dark-300 my-3 flex w-[22rem] justify-between rounded-lg bg-white px-2 py-1.5 shadow-sm sm:w-[24rem]">
<div class="flex gap-3 text-sm">
<button
···
</div>
<div class="flex gap-1">
<Show when={agent() && agent()?.sub === record()?.uri.split("/")[2]}>
-
<RecordEditor create={false} record={record()?.value} />
<Tooltip text="Delete">
<button
class="flex items-center rounded-sm p-1 hover:bg-neutral-100 active:bg-neutral-100 dark:hover:bg-neutral-600 dark:active:bg-neutral-600"
···
</div>
</div>
<Show when={!showBacklinks()}>
<div class="w-[22rem] font-mono text-xs wrap-anywhere whitespace-pre-wrap sm:w-full sm:text-sm">
<JSONValue data={record()?.value as any} repo={record()!.uri.split("/")[2]} />
</div>
···
</Suspense>
</ErrorBoundary>
</Show>
-
</Show>
-
</div>
);
};
···
import { CredentialManager, Client } from "@atcute/client";
import { useNavigate, useParams } from "@solidjs/router";
+
import { createResource, createSignal, ErrorBoundary, Show, Suspense } from "solid-js";
import { Backlinks } from "../components/backlinks.jsx";
import { JSONValue } from "../components/json.jsx";
···
import { didDocCache, resolvePDS } from "../utils/api.js";
import { AtUri, uriTemplates } from "../utils/templates.js";
import { verifyRecord } from "../utils/verify.js";
+
import { ActorIdentifier, is } from "@atcute/lexicons";
import { lexiconDoc } from "@atcute/lexicon-doc";
import { lexicons } from "../utils/types/lexicons.js";
import { RecordEditor } from "../components/create.jsx";
import { addToClipboard } from "../utils/copy.js";
···
export const RecordView = () => {
const navigate = useNavigate();
const params = useParams();
const [openDelete, setOpenDelete] = createSignal(false);
const [notice, setNotice] = createSignal("");
const [showBacklinks, setShowBacklinks] = createSignal(false);
···
const did = params.repo;
let rpc: Client;
+
const fetchRecord = async () => {
setCID(undefined);
setValidRecord(undefined);
setValidSchema(undefined);
···
setNotice(res.data.error);
throw new Error(res.data.error);
}
setCID(res.data.cid);
setExternalLink(checkUri(res.data.uri, res.data.value));
···
console.error(err);
setValidRecord(false);
}
+
+
return res.data;
+
};
+
+
const [record, { refetch }] = createResource(fetchRecord);
const deleteRecord = async () => {
rpc = new Client({ handler: agent()! });
···
};
return (
+
<Show when={record()} keyed>
+
<div class="flex w-full flex-col items-center">
<div class="dark:shadow-dark-900/80 dark:bg-dark-300 my-3 flex w-[22rem] justify-between rounded-lg bg-white px-2 py-1.5 shadow-sm sm:w-[24rem]">
<div class="flex gap-3 text-sm">
<button
···
</div>
<div class="flex gap-1">
<Show when={agent() && agent()?.sub === record()?.uri.split("/")[2]}>
+
<RecordEditor create={false} record={record()?.value} refetch={refetch} />
<Tooltip text="Delete">
<button
class="flex items-center rounded-sm p-1 hover:bg-neutral-100 active:bg-neutral-100 dark:hover:bg-neutral-600 dark:active:bg-neutral-600"
···
</div>
</div>
<Show when={!showBacklinks()}>
+
<Show when={validRecord() === false}>
+
<div class="mb-2 break-words text-red-500 dark:text-red-400">{notice()}</div>
+
</Show>
<div class="w-[22rem] font-mono text-xs wrap-anywhere whitespace-pre-wrap sm:w-full sm:text-sm">
<JSONValue data={record()?.value as any} repo={record()!.uri.split("/")[2]} />
</div>
···
</Suspense>
</ErrorBoundary>
</Show>
+
</div>
+
</Show>
);
};