tangled
alpha
login
or
join now
zzstoatzz.io
/
slides
5
fork
atom
powerpointproto
slides.waow.tech
slides
5
fork
atom
overview
issues
pulls
pipelines
fix: resolve PDS URLs for public gallery thumbnails
zzstoatzz.io
1 month ago
47b0ccdb
d3b348a2
+37
-37
1 changed file
expand all
collapse all
unified
split
src
routes
+page.svelte
+37
-37
src/routes/+page.svelte
···
3
3
import { goto } from "$app/navigation";
4
4
import { editorState, newDeck, loadDeck, startPresenting } from "$lib/state.svelte";
5
5
import { auth, initAuth, doDeleteDeck } from "$lib/auth.svelte";
6
6
-
import { getDeck, getBlobUrl, type Deck } from "$lib/api";
6
6
+
import { getDeck, getBlobUrl, resolvePdsUrl, type Deck } from "$lib/api";
7
7
import Toolbar from "$lib/components/Toolbar.svelte";
8
8
import SlideList from "$lib/components/SlideList.svelte";
9
9
import SlideCanvas from "$lib/components/SlideCanvas.svelte";
···
29
29
if (!res.ok) return;
30
30
const records = await res.json();
31
31
32
32
-
// Map to our format
33
33
-
const decks: PublicDeck[] = records.map((r: {
32
32
+
// Get unique DIDs and resolve their PDS URLs + handles in parallel
33
33
+
type RecordType = {
34
34
did: string;
35
35
rkey: string;
36
36
record: {
···
38
38
slides: unknown[];
39
39
thumbnail?: { ref: { $link: string }; mimeType: string };
40
40
};
41
41
-
}) => ({
41
41
+
};
42
42
+
const dids = [...new Set(records.map((r: RecordType) => r.did))];
43
43
+
const pdsMap = new Map<string, string>();
44
44
+
const handleMap = new Map<string, string>();
45
45
+
46
46
+
await Promise.all([
47
47
+
// Resolve PDS URLs
48
48
+
...dids.map(async (did) => {
49
49
+
try {
50
50
+
const pdsUrl = await resolvePdsUrl(did);
51
51
+
pdsMap.set(did, pdsUrl);
52
52
+
} catch {}
53
53
+
}),
54
54
+
// Resolve handles via getProfiles
55
55
+
(async () => {
56
56
+
if (dids.length > 0) {
57
57
+
try {
58
58
+
const params = dids.map((d: string) => `actors=${d}`).join("&");
59
59
+
const res = await fetch(`https://public.api.bsky.app/xrpc/app.bsky.actor.getProfiles?${params}`);
60
60
+
if (res.ok) {
61
61
+
const data = await res.json();
62
62
+
for (const profile of data.profiles || []) {
63
63
+
handleMap.set(profile.did, profile.handle);
64
64
+
}
65
65
+
}
66
66
+
} catch {}
67
67
+
}
68
68
+
})(),
69
69
+
]);
70
70
+
71
71
+
// Map to our format with resolved PDS URLs
72
72
+
const decks: PublicDeck[] = records.map((r: RecordType) => ({
42
73
did: r.did,
43
74
rkey: r.rkey,
44
75
name: r.record.name || "untitled",
45
76
slideCount: r.record.slides?.length || 0,
46
77
thumbnailUrl: r.record.thumbnail
47
47
-
? getBlobUrl(r.did, r.record.thumbnail.ref.$link)
78
78
+
? getBlobUrl(r.did, r.record.thumbnail.ref.$link, pdsMap.get(r.did))
48
79
: undefined,
80
80
+
handle: handleMap.get(r.did),
49
81
}));
50
50
-
51
51
-
// Resolve handles in parallel
52
52
-
const dids = [...new Set(decks.map(d => d.did))];
53
53
-
const handleMap = new Map<string, string>();
54
54
-
55
55
-
await Promise.all(dids.map(async (did) => {
56
56
-
try {
57
57
-
const res = await fetch(`https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?did=${did}`);
58
58
-
if (res.ok) {
59
59
-
// This endpoint doesn't exist, use getProfile instead
60
60
-
}
61
61
-
} catch {}
62
62
-
}));
63
63
-
64
64
-
// Use getProfiles to batch resolve
65
65
-
if (dids.length > 0) {
66
66
-
try {
67
67
-
const params = dids.map(d => `actors=${d}`).join("&");
68
68
-
const res = await fetch(`https://public.api.bsky.app/xrpc/app.bsky.actor.getProfiles?${params}`);
69
69
-
if (res.ok) {
70
70
-
const data = await res.json();
71
71
-
for (const profile of data.profiles || []) {
72
72
-
handleMap.set(profile.did, profile.handle);
73
73
-
}
74
74
-
}
75
75
-
} catch {}
76
76
-
}
77
77
-
78
78
-
// Apply handles
79
79
-
for (const deck of decks) {
80
80
-
deck.handle = handleMap.get(deck.did);
81
81
-
}
82
82
83
83
publicDecks = decks;
84
84
} catch (e) {