ActivityFeed — replaced the <button> inside <a> (invalid HTML, unreliable) with the stretched-link pattern: the card is now a <div>, the title <a> carries a ::before pseudo-element

that covers the whole card making it clickable, and @handle is a proper <a> with z-index: 10 sitting above the stretched link. Clicking the handle navigates to /u/{handle}/; clicking
  anywhere else navigates to the activity.

  ActivityDetail — @handle link added in the date/time row of the header, linking to /u/{handle}/. Only shown when activity.handle is set (i.e. multi-user mode).
This commit is contained in:
Davide Scaini
2026-04-09 12:32:22 +02:00
parent 7dcb1e6dd0
commit 50cdeb3b6e
4 changed files with 50 additions and 18 deletions
+16 -3
View File
@@ -19,13 +19,26 @@ export async function getStaticPaths() {
const root: BASIndex = JSON.parse(readFileSync(join(dataDir, 'index.json'), 'utf-8'));
// Collect activities from root (single-user) or walk shards (multi-user)
function readActivities(indexPath: string): ActivitySummary[] {
function readActivities(indexPath: string, urlPrefix: string = ''): ActivitySummary[] {
try {
const idx: BASIndex = JSON.parse(readFileSync(indexPath, 'utf-8'));
const own = idx.activities ?? [];
const own = (idx.activities ?? []).map(a =>
urlPrefix
? {
...a,
detail_url: a.detail_url && !a.detail_url.startsWith('http') ? `${urlPrefix}${a.detail_url}` : a.detail_url,
track_url: a.track_url && !a.track_url.startsWith('http') ? `${urlPrefix}${a.track_url}` : a.track_url,
}
: a
);
const fromShards = (idx.shards ?? []).flatMap(s => {
const shardPath = join(dataDir, s.url);
return readActivities(shardPath);
// Prefix for activities read from this shard: path of the shard dir relative to dataDir
const shardDir = s.url.substring(0, s.url.lastIndexOf('/') + 1);
return readActivities(shardPath, shardDir).map(a => ({
...a,
...(s.handle && !a.handle ? { handle: s.handle } : {}),
}));
});
return [...own, ...fromShards];
} catch {