tangled
alpha
login
or
join now
vielle.dev
/
pdsls
forked from
pds.ls/pdsls
0
fork
atom
atproto explorer
0
fork
atom
overview
issues
pulls
pipelines
refetch record after editing
handle.invalid
6 months ago
0f760da4
e392b162
+30
-41
5 changed files
expand all
collapse all
unified
split
src
components
create.tsx
views
blob.tsx
collection.tsx
pds.tsx
record.tsx
+2
-2
src/components/create.tsx
···
11
11
import { Modal } from "./modal.jsx";
12
12
import { Button } from "./button.jsx";
13
13
14
14
-
export const RecordEditor = (props: { create: boolean; record?: any }) => {
14
14
+
export const RecordEditor = (props: { create: boolean; record?: any; refetch?: any }) => {
15
15
const navigate = useNavigate();
16
16
const params = useParams();
17
17
const [openDialog, setOpenDialog] = createSignal(false);
···
119
119
}
120
120
}
121
121
setOpenDialog(false);
122
122
-
window.location.reload();
122
122
+
props.refetch();
123
123
} catch (err: any) {
124
124
setNotice(err.message);
125
125
}
+5
-8
src/views/blob.tsx
···
8
8
const [cursor, setCursor] = createSignal<string>();
9
9
let rpc: Client;
10
10
11
11
-
const listBlobs = (did: string, cursor: string | undefined) =>
12
12
-
rpc.get("com.atproto.sync.listBlobs", {
11
11
+
const fetchBlobs = async () => {
12
12
+
if (!rpc) rpc = new Client({ handler: new CredentialManager({ service: props.pds }) });
13
13
+
const res = await rpc.get("com.atproto.sync.listBlobs", {
13
14
params: {
14
14
-
did: did as `did:${string}:${string}`,
15
15
+
did: props.repo as `did:${string}:${string}`,
15
16
limit: LIMIT,
16
16
-
cursor: cursor,
17
17
+
cursor: cursor(),
17
18
},
18
19
});
19
19
-
20
20
-
const fetchBlobs = async () => {
21
21
-
if (!rpc) rpc = new Client({ handler: new CredentialManager({ service: props.pds }) });
22
22
-
const res = await listBlobs(props.repo, cursor());
23
20
if (!res.ok) throw new Error(res.data.error);
24
21
if (!res.data.cids) return [];
25
22
setCursor(res.data.cids.length < LIMIT ? undefined : res.data.cursor);
+6
-9
src/views/collection.tsx
···
75
75
let pds: string;
76
76
let rpc: Client;
77
77
78
78
-
const listRecords = (did: string, collection: string, cursor: string | undefined) =>
79
79
-
rpc.get("com.atproto.repo.listRecords", {
78
78
+
const fetchRecords = async () => {
79
79
+
if (!pds) pds = await resolvePDS(did);
80
80
+
if (!rpc) rpc = new Client({ handler: new CredentialManager({ service: pds }) });
81
81
+
const res = await rpc.get("com.atproto.repo.listRecords", {
80
82
params: {
81
83
repo: did as ActorIdentifier,
82
82
-
collection: collection as `${string}.${string}.${string}`,
84
84
+
collection: params.collection as `${string}.${string}.${string}`,
83
85
limit: LIMIT,
84
84
-
cursor: cursor,
86
86
+
cursor: cursor(),
85
87
reverse: reverse(),
86
88
},
87
89
});
88
88
-
89
89
-
const fetchRecords = async () => {
90
90
-
if (!pds) pds = await resolvePDS(did);
91
91
-
if (!rpc) rpc = new Client({ handler: new CredentialManager({ service: pds }) });
92
92
-
const res = await listRecords(did, params.collection, cursor());
93
90
if (!res.ok) throw new Error(res.data.error);
94
91
setCursor(res.data.records.length < LIMIT ? undefined : res.data.cursor);
95
92
const tmpRecords: AtprotoRecord[] = [];
+1
-3
src/views/pds.tsx
···
28
28
setVersion((res.data as any).version);
29
29
};
30
30
31
31
-
const fetchRepos = async (): Promise<
32
32
-
InferXRPCBodyOutput<ComAtprotoSyncListRepos.mainSchema["output"]>
33
33
-
> => {
31
31
+
const fetchRepos = async () => {
34
32
await getVersion();
35
33
const describeRes = await rpc.get("com.atproto.server.describeServer");
36
34
if (!describeRes.ok) console.error(describeRes.data.error);
+16
-19
src/views/record.tsx
···
1
1
import { CredentialManager, Client } from "@atcute/client";
2
2
3
3
import { useNavigate, useParams } from "@solidjs/router";
4
4
-
import { createSignal, ErrorBoundary, onMount, Show, Suspense } from "solid-js";
4
4
+
import { createResource, createSignal, ErrorBoundary, Show, Suspense } from "solid-js";
5
5
6
6
import { Backlinks } from "../components/backlinks.jsx";
7
7
import { JSONValue } from "../components/json.jsx";
···
11
11
import { didDocCache, resolvePDS } from "../utils/api.js";
12
12
import { AtUri, uriTemplates } from "../utils/templates.js";
13
13
import { verifyRecord } from "../utils/verify.js";
14
14
-
import { ActorIdentifier, InferXRPCBodyOutput, is } from "@atcute/lexicons";
14
14
+
import { ActorIdentifier, is } from "@atcute/lexicons";
15
15
import { lexiconDoc } from "@atcute/lexicon-doc";
16
16
-
import { ComAtprotoRepoGetRecord } from "@atcute/atproto";
17
16
import { lexicons } from "../utils/types/lexicons.js";
18
17
import { RecordEditor } from "../components/create.jsx";
19
18
import { addToClipboard } from "../utils/copy.js";
···
24
23
export const RecordView = () => {
25
24
const navigate = useNavigate();
26
25
const params = useParams();
27
27
-
const [record, setRecord] =
28
28
-
createSignal<InferXRPCBodyOutput<ComAtprotoRepoGetRecord.mainSchema["output"]>>();
29
26
const [openDelete, setOpenDelete] = createSignal(false);
30
27
const [notice, setNotice] = createSignal("");
31
28
const [showBacklinks, setShowBacklinks] = createSignal(false);
···
35
32
const did = params.repo;
36
33
let rpc: Client;
37
34
38
38
-
onMount(async () => {
35
35
+
const fetchRecord = async () => {
39
36
setCID(undefined);
40
37
setValidRecord(undefined);
41
38
setValidSchema(undefined);
···
53
50
setNotice(res.data.error);
54
51
throw new Error(res.data.error);
55
52
}
56
56
-
setRecord(res.data);
57
53
setCID(res.data.cid);
58
54
setExternalLink(checkUri(res.data.uri, res.data.value));
59
55
···
87
83
console.error(err);
88
84
setValidRecord(false);
89
85
}
90
90
-
});
86
86
+
87
87
+
return res.data;
88
88
+
};
89
89
+
90
90
+
const [record, { refetch }] = createResource(fetchRecord);
91
91
92
92
const deleteRecord = async () => {
93
93
rpc = new Client({ handler: agent()! });
···
112
112
};
113
113
114
114
return (
115
115
-
<div class="flex w-full flex-col items-center">
116
116
-
<Show when={record() === undefined && validRecord() !== false}>
117
117
-
<div class="iconify lucide--loader-circle mt-3 animate-spin text-xl" />
118
118
-
</Show>
119
119
-
<Show when={validRecord() === false}>
120
120
-
<div class="mt-3 break-words text-red-500 dark:text-red-400">{notice()}</div>
121
121
-
</Show>
122
122
-
<Show when={record()}>
115
115
+
<Show when={record()} keyed>
116
116
+
<div class="flex w-full flex-col items-center">
123
117
<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]">
124
118
<div class="flex gap-3 text-sm">
125
119
<button
···
147
141
</div>
148
142
<div class="flex gap-1">
149
143
<Show when={agent() && agent()?.sub === record()?.uri.split("/")[2]}>
150
150
-
<RecordEditor create={false} record={record()?.value} />
144
144
+
<RecordEditor create={false} record={record()?.value} refetch={refetch} />
151
145
<Tooltip text="Delete">
152
146
<button
153
147
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"
···
204
198
</div>
205
199
</div>
206
200
<Show when={!showBacklinks()}>
201
201
+
<Show when={validRecord() === false}>
202
202
+
<div class="mb-2 break-words text-red-500 dark:text-red-400">{notice()}</div>
203
203
+
</Show>
207
204
<div class="w-[22rem] font-mono text-xs wrap-anywhere whitespace-pre-wrap sm:w-full sm:text-sm">
208
205
<JSONValue data={record()?.value as any} repo={record()!.uri.split("/")[2]} />
209
206
</div>
···
219
216
</Suspense>
220
217
</ErrorBoundary>
221
218
</Show>
222
222
-
</Show>
223
223
-
</div>
219
219
+
</div>
220
220
+
</Show>
224
221
);
225
222
};