tangled
alpha
login
or
join now
tynanpurdy.com
/
atprofile
3
fork
atom
Fork of atp.tools as a universal profile for people on the ATmosphere
3
fork
atom
overview
issues
pulls
pipelines
minimum prototype of simplified handle page
Tynan Purdy
8 months ago
c97c456f
2e0d3c96
+52
-27
2 changed files
expand all
collapse all
unified
split
src
components
repoIcons.tsx
routes
at:
$handle.index.tsx
+19
-6
src/components/repoIcons.tsx
···
68
return matchingKey ? iconMappings[matchingKey] : null;
69
}
70
0
0
0
0
0
71
function RepoIcons({
72
collections,
73
did,
···
79
}) {
80
let uniqueTypes = Array.from(
81
collections
82
-
.map((collection) => ({
83
-
id: collection,
84
-
Icon: getIconForCollection(collection)?.icon ?? <ShieldQuestionIcon />,
85
-
displayName: getIconForCollection(collection)?.label ?? "Unknown",
86
-
linkTemplate: getIconForCollection(collection)?.linkTemplate,
87
-
}))
0
0
0
0
0
0
88
.reduce((acc, current) => {
89
if (
90
!Array.from(acc.values()).some(
···
107
<a
108
href={linkTemplate?.replace("{handle}", handle).replace("{did}", did)}
109
key={id}
0
0
110
>
111
<div className="w-8 h-8 p-1 mr-2 rounded-full dark:bg-neutral-800 border border-neutral-500/50 text-white">
112
{typeof Icon === "string" ? (
···
68
return matchingKey ? iconMappings[matchingKey] : null;
69
}
70
71
+
function reverseDomain(collection: string) {
72
+
// Split by dot, reverse, join with dot
73
+
return collection.split(".").reverse().join(".");
74
+
}
75
+
76
function RepoIcons({
77
collections,
78
did,
···
84
}) {
85
let uniqueTypes = Array.from(
86
collections
87
+
.map((collection) => {
88
+
const iconObj = getIconForCollection(collection);
89
+
return {
90
+
id: collection,
91
+
Icon: iconObj?.icon ?? <ShieldQuestionIcon />,
92
+
displayName: iconObj?.label ?? "Unknown",
93
+
// If linkTemplate exists, use it; else generate URL from reversed domain
94
+
linkTemplate:
95
+
iconObj?.linkTemplate ??
96
+
`https://${reverseDomain(collection)}/{did}`,
97
+
};
98
+
})
99
.reduce((acc, current) => {
100
if (
101
!Array.from(acc.values()).some(
···
118
<a
119
href={linkTemplate?.replace("{handle}", handle).replace("{did}", did)}
120
key={id}
121
+
target="_blank"
122
+
rel="noopener noreferrer"
123
>
124
<div className="w-8 h-8 p-1 mr-2 rounded-full dark:bg-neutral-800 border border-neutral-500/50 text-white">
125
{typeof Icon === "string" ? (
+33
-21
src/routes/at:/$handle.index.tsx
···
252
<div className="pt-2">
253
<h2 className="text-xl font-bold mb-1">Collections</h2>
254
<ul className="list-inside space-y-1">
255
-
{data.collections.map((c, i) => (
256
-
<Fragment key={c}>
257
-
{c.split(".").slice(0, 2).join(".") !=
258
-
(i > 0 &&
259
-
data.collections[i - 1]
260
-
.split(".")
261
-
.slice(0, 2)
262
-
.join(".")) && (
263
-
<div className="w-min pt-2">
264
-
{c.split(".").slice(0, 2).join(".")}{" "}
265
-
</div>
266
-
)}
267
-
<li>
0
0
0
0
0
0
0
0
0
0
0
268
<Link
269
-
className="ml-4 text-blue-600 dark:text-blue-400 hover:no-underline border-b hover:border-border border-transparent w-min"
270
to="/at:/$handle/$collection"
271
params={{
272
-
handle: handle, // Use original handle for navigation consistency
273
-
collection: c,
274
}}
0
275
>
276
-
{c}
277
</Link>
278
</li>
279
-
</Fragment>
280
-
))}
281
</ul>
282
</div>
283
)}
···
309
</Accordion>
310
)}
311
{/* Backlinks Section */}
312
-
{data?.did && (
313
<div className="pt-4 pb-8 flex flex-col gap-2">
314
<AllBacklinksViewer aturi={data.did} />
315
</div>
316
-
)}
317
</div>
318
</div>
319
);
···
252
<div className="pt-2">
253
<h2 className="text-xl font-bold mb-1">Collections</h2>
254
<ul className="list-inside space-y-1">
255
+
{Array.from(
256
+
data.collections
257
+
.reduce((map, c) => {
258
+
const prefix = c.split(".").slice(0, 2).join(".");
259
+
if (!map.has(prefix)) {
260
+
map.set(prefix, prefix);
261
+
}
262
+
return map;
263
+
}, new Map<string, string>())
264
+
.values(),
265
+
).map((prefix) => {
266
+
const domain = prefix.split(".").reverse().join(".");
267
+
const faviconUrl = `https://www.google.com/s2/favicons?sz=64&domain=${domain}`;
268
+
return (
269
+
<li key={prefix} className="flex items-center gap-2">
270
+
<img
271
+
src={faviconUrl}
272
+
alt={`${domain} favicon`}
273
+
className="w-4 h-4 rounded-sm flex-shrink-0"
274
+
onError={(e) => {
275
+
// Hide image if favicon not found
276
+
(e.target as HTMLImageElement).style.display = "none";
277
+
}}
278
+
/>
279
<Link
280
+
className="text-blue-600 dark:text-blue-400 hover:no-underline border-b hover:border-border border-transparent flex-1 break-all"
281
to="/at:/$handle/$collection"
282
params={{
283
+
handle: handle,
284
+
collection: prefix,
285
}}
286
+
title={`https://${domain}`}
287
>
288
+
{`https://${domain}`}
289
</Link>
290
</li>
291
+
);
292
+
})}
293
</ul>
294
</div>
295
)}
···
321
</Accordion>
322
)}
323
{/* Backlinks Section */}
324
+
{/* {data?.did && (
325
<div className="pt-4 pb-8 flex flex-col gap-2">
326
<AllBacklinksViewer aturi={data.did} />
327
</div>
328
+
)} */}
329
</div>
330
</div>
331
);